Jump to content
IGNORED

Need my code scrutinized >.>


Recommended Posts

I have no doubt that I'm making all sorts of careless mistakes, but seeing as I'm new to this, and I took the first step into actually coding something, I figured I'd inquire about it.

 

Okay, so my code is doing horrible things to me. Currently, this is what happens:

 

whalesmashscrewup.png

 

I think the problem currently lies in my horrible math skills and not being able to get the TIM64T calculations correct, so it's messing with the vertical blank period and everything else, as well.

 

However, I could be being careless and using waayyyyy too many cycles or jumping page boundaries, thus effectively ruining the entire code.

 

Then again, I could just simply not get it and have screwed the entire thing up.

 

I just need it checked. I'm not exactly sure what I'm doing wrong.

 

Code is attached.

 

EDIT: If there are too many things wrong, just tell me and I'll start over or something, lol

 

NOTE: The rabbit graphics are completely left out currently. They're sitting there waiting for use.

whaleman.zip

Edited by johnon
Link to comment
Share on other sites

You're doing way to many scanlines. After your Vsync, load TIM64T with a value to do 37 scanlines. After that expires draw your visible screen. This is the part where you added a ton more lines. When you load the color for the background, you put that in a loop that did almost 176 lines alone.

Link to comment
Share on other sites

You're doing way to many scanlines. After your Vsync, load TIM64T with a value to do 37 scanlines. After that expires draw your visible screen. This is the part where you added a ton more lines. When you load the color for the background, you put that in a loop that did almost 176 lines alone.

Ah, aight...eehhhh, yeah. Here's the part where I don't really get how to do this. I'd been doing that loop to change the background at that scanline. I'm not sure how to change it, otherwise. Any insight on that?

 

I assumed it was probably too many scanlines. I don't have much practice with it, so I figured there was a lot of carelessness going on.

 

EDIT: On a side-note, I did change the TIM64T. I assumed I'd need a smaller value than that, due to having a lot going on in-between it.

Edited by johnon
Link to comment
Share on other sites

When you load the color for the background, you put that in a loop that did almost 176 lines alone.

Wait, wait, wait...

 

So, after going back through other random things I've done, I rediscovered this. How come, once I fixed my careless error of leaving out "ldx #0" and "inx", that worked there, but now, here, when I do the same thing, it doesn't?

Link to comment
Share on other sites

You're drawing:

 

Background

sta WSYNC

lda #$70

sta COLUBK

inx

cpx #176

bne Background

BackgroundScore

sta WSYNC

lda #$08

sta COLUBK

inx

cpx #192

bne BackgroundScore

 

Notice after this point X = 192 scanlines already drawn. That's your entire visible screen. You need to put your playfield code in the same loop, not after it. Otherwise you're doing almost double the scanlines you should be.

Link to comment
Share on other sites

Notice after this point X = 192 scanlines already drawn. That's your entire visible screen. You need to put your playfield code in the same loop, not after it. Otherwise you're doing almost double the scanlines you should be.

Right, so then, I have to add the drawing the player in there, as well, or no?

 

Also, was there anything else terribly wrong with it besides that?

Edited by johnon
Link to comment
Share on other sites

I don't have time right now to try to figure out everything, but here are some quick comments:

 

StartOfFrame

lda #0

sta VBLANK

lda #2

sta VSYNC

sta WSYNC

sta WSYNC

sta WSYNC

lda #0

sta VSYNC

ldx #0

Background

There are two or three problems with this section.

 

First, you need to turn VBLANK *on* before/during the VSYNC signal, but your code is turning it *off*, not on. Moving 2 to VBLANK turns it on, and moving 0 to VBLANK turns it off.

 

Second, you really should do a WSYNC just before turning VSYNC on, and again just before turning VSYNC off, to be sure VSYNC stays on for at least 3 full lines. Since you aren't doing WSYNC before VSYNC, you don't know how far into the scan line the beams are when you turn on VSYNC.

 

Third (which is a suggestion, not a problem), you can ensure that VSYNC gets turned on or off as soon after the scan line begins by moving the desired value into the register before WSYNC, then store that value into WSYNC and VSYNC one after the other.

 

Fourth (this is another suggestion), you can improve the readability of your code by taking out some of those blank lines. I find it helpful to keep the LDA and STA together, but that's my own preference, so you need to develop your own style instead of letting people like me tell you what style to use! :)

 

Anyway, here's how I might suggest changing that section of code:

 

StartOfFrame

lda #2
sta VBLANK
sta WSYNC
sta VSYNC

lda #0
sta WSYNC
sta WSYNC
sta WSYNC
sta VSYNC

ldx #0

Background

There's a shorter way to do the VSYNC routine, by the way (byte-wise), which can be found in the macro.h file, but the method shown works fine, and is more straightforward to understand.

 

Also, you'd probably have already turned VBLANK on at the bottom of the previous screen, so if you start drawing at the bottom first-- the part that the Stella programming guide labels "overscan"-- then you can save a couple of bytes by not having to turn VBLANK on again just before do the WSYNC/VSYNC combo, since VBLANK will already be on, anyway.

 

To continue:

 

ldx #0

Background

sta WSYNC

lda #$70

sta COLUBK

inx

cpx #176

bne Background

BackgroundScore

This code is being done right after turning off VSYNC, so it's starting during the section that the Stella programming guide calls the "vertical blank." You have VBLANK turned off at this point anyway, so the background color is being drawn, but what you really should be doing is waiting a bit after the VSYNC-- the Stella programming guide suggests 37 lines-- before you turn off VBLANK and start drawing the visible picture. The normal way of doing this is to set the timer for the "overscan" period, and then set it again for the "vertical blank" period.

 

Additionally, you're incrementing the X register while drawing the "active" (or visible, non-blanked) lines, but you can save a few bytes and a few cycles if you *decrement* X instead.

 

Here's how I might do it, putting the "overscan" first, and setting the timer:

 

Overscan

lda #2
sta VBLANK ; turn on the blanking (this is at the bottom of the visible picture)

lda #35    ; this is about equal to 30 lines
sta TIM64T

; normally you would use this time to do stuff like process collisions that occurred,
; update the screen positions of the sprites, etc., then wait for the timer to go off
; (i.e., the TIMINT flag that indicates the timer finished counting down)

OverscanLoop

bit TIMINT
bpl OverscanLoop

lda #2
sta WSYNC
sta VSYNC

lda #0
sta WSYNC
sta WSYNC
sta WSYNC
sta VSYNC

lda #43    ; this is about equal to 37 lines
sta TIM64T

; again, you would normally use this time to do stuff, then wait for the timer to go off

StartOfFrame

bit TIMINT
bpl StartOfFrame

lda #0
sta WSYNC
sta VBLANK ; now you can turn off the blanking

ldx #192   ; set X to the number of lines you want to draw

Background

lda #$70
sta COLUBK
sta WSYNC

dex        ; decrement X
bne Background

jmp Overscan

I didn't try to include any of your graphics, because I wanted to keep this example simple, but mostly because I haven't tried to figure out everything you're trying to do! :) When I compile this simple kernel and run it, Stella says I have 262 lines exactly.

 

The way you figure out what to set the timer to is as follows:

 

Example 1 (overscan): I want the Atari to draw 30 blank lines while I do other stuff.

 

1 line = 76 cycles, so 30 lines = 30 * 76 = 2280 cycles.

 

If I want to set TIM64T, then each "tick" of the timer will be 64 cycles, so I divide the number by 64:

 

2280 / 64 = 35.625

 

If I round down, I get 35, so I set TIM64T to 35 to get about 30 lines. I may end up having to increase or decrease that value if I end up with more or fewer than 262 lines, but in this case it comes out just right.

 

After you've set the timer, then done the stuff you need to do (collision processing, updating positions, etc.), you can check the timer by using the bit instruction on TIMINT. The bit instruction will copy the highest two bits of the memory address being checked into bits 7 and 6 of the status register, and the timer interrupt flag is bit 7 of TIMINT, so as long as bit TIMINT comes back positive (meaning bit 7 is *not* set yet), it means the timer is still counting down the requested number of "ticks" or time periods (in this case, 64 cycles per "tick"). When bit TIMINT comes back negative, it means the timer interrupt flag has been set, meaning the timer counted down to 0 and then wrapped around to 255.

 

Example 2 (the rest of the vertical blank): I want the Atari to draw 37 blank lines while I do other stuff.

 

1 line = 76 cycles, so 37 lines = 37 * 76 = 2812 cycles

2812 / 64 = 43.9375, so I set TIM64T to 43 to get about 37 lines.

 

Michael

  • Like 1
Link to comment
Share on other sites

Another note: You don't need to set COLUBK on each line, *unless* you want to be able to change it on each line. You can set it once, before you start looping to draw the lines, then forget about it, until you want to change it to something different. For example:

 

Overscan

lda #2
sta VBLANK

lda #35
sta TIM64T

OverscanLoop

bit TIMINT
bpl OverscanLoop

lda #2
sta WSYNC
sta VSYNC

lda #0
sta WSYNC
sta WSYNC
sta WSYNC
sta VSYNC

lda #43
sta TIM64T

StartOfFrame

bit TIMINT
bpl StartOfFrame

lda #0
sta WSYNC
sta VBLANK

lda #$70  ; dark purple
sta COLUBK

ldx #96   ; to draw 96 lines of dark purple

Background1

sta WSYNC

dex
bne Background1

lda #$AC  ; light blue
sta COLUBK

ldx #96   ; to draw 96 lines of light blue

Background2

sta WSYNC

dex        ; decrement X
bne Background2

jmp Overscan

Michael

post-7456-127061862269_thumb.png

Link to comment
Share on other sites

Okay, thanks Michael for the time typing that up. ^^

 

Mainly, it looks like my problem is that I'm mixing up where I'm putting overscan and everything compared to where it's supposed to be appropriately placed in this kernel.

Link to comment
Share on other sites

Another note: You don't need to set COLUBK on each line, *unless* you want to be able to change it on each line. You can set it once, before you start looping to draw the lines, then forget about it, until you want to change it to something different.

 

The main reason I did it the way I've been doing it is because I'm not used to the timing thing quite yet. I will take your advice and use a decrement, rather than an increment, but as far as timing everything perfectly to make changes, I can't quite figure it out in my head yet where I'd need to change it. Any advice for this is perfectly welcome :D

 

Anyways, once again, thanks for the long version of it. I read through it all, and I'll apply it to my code tomorrow. For tonight, I should probably crash so that I can get up in the morning.

 

EDIT: After reading through the first post you made, I can definitely see what I did wrong. A lot of it is, in fact, a huge misordering of everything, combined with using too many scanlines on background loops.

Edited by johnon
Link to comment
Share on other sites

Okay, admittedly, I couldn't leave it alone. I tried again, reordering it and using the example from the first post by SeaGtGruff, but now the screen's completely black.

 

Code is attached. Still not sure where everything goes.

 

And since SeaGt mentioned not knowing what I was attempting to do, there should be, on the top half of the screen, a playfield of changing greens (deepest color on top, descending to lighter colors), and a background on the bottom half that's a blue, which then changes to black in the last 16 scanlines. On top of this, there should be a "whaleman" P0 drawn, that can be moved around, which should also be animated.

 

As of yet, that's all that is intended to be happening. Apparently, none of which is happening.

whalemansmash.zip

Link to comment
Share on other sites

Mainly, it looks like my problem is that I'm mixing up where I'm putting overscan and everything compared to where it's supposed to be appropriately placed in this kernel.

Not necessarily! This is where personal preference can play a part. I like to put the "overscan" first because then I don't need to turn VBLANK on twice-- once at StartOfFrame before VSYNC, then again at the very bottom of the frame that people like to call the "overscan." I think most people seem to start at the VSYNC like you did, then put the Overscan at the bottom before they loop back up to the VSYNC for the "vertical blank."

 

I have a personal issue with those terms the way they're used, because technically "overscan" means to draw the picture bigger than the viewable area of the TV screen, so the "overscanned area" is the part of the picture that can't be seen-- on all four sides, top, bottom, left, and right-- because it runs past the edges of the TV screen. Atari programmers deliberately "underscan" the picture (draw it smaller than the TV screen) to make sure it's all visible, which is why you can see the blanking (or black "border" area) surrounding the game screen at the top, bottom, left, and right sides of the TV screen. And "vertical blank" includes *all* of the lines that are blanked, both at the bottom of the picture and at the top. So I personally avoid using those terms the way they're used by most Atari programmers-- but that's *me*. ;)

 

Personally, I like to use the term "front porch" for what other Atari programmers call the "overscan" area, and "back porch" for what they call the "vertical blank" area, because those are terms that video engineers use. (I am definitely *not* a video engineer, by the way.) There are actually two types of "front porch" and "back porch" periods-- vertical and horizontal:

 

end of the "visible" portion of the scan line

turn on horizontal blanking

turn on horizontal sync

turn off horizontal sync

do colorburst

turn off horizontal blanking

start of the "visible" portion of the (next) scan line

-- the "horizontal front porch" is the part of the horizontal blanking that comes *before* horizontal sync

-- the "horizontal back porch" is the part of the horizontal blanking that comes *after* horizontal sync

-- the "breezeway" is the part of the horizontal back porch that comes between the end of horizontal sync and the colorburst

 

end of the "visible" or "active" scan lines

turn on vertical blanking

turn on vertical sync

turn off vertical sync

turn off vertical blanking

start of the "visible" or "active" scan lines

-- the "vertical front porch" is the part of the vertical blanking that comes *before* vertical sync

-- the "vertical back porch" is the part of the vertical blanking that comes *after* vertical sync

 

The Atari autmatically handles all of the horizontal blanking, horizontal sync, and colorburst by itself, so we don't have to worry about it. All we have to do is worry about the vertical blanking and vertical sync. So I normally just say "front porch" instead of "vertical front porch," and "back porch" instead of "vertical back porch."

 

I've been chastised for using these terms that aren't familiar to most Atari programmers, and probably rightly so, since they can just confuse people. But like I said-- that's just me! :D

 

Anyway, there's nothing at all wrong with doing the VSYNC at the start of the loop, and doing the so-called "overscan" at the end of the loop.

 

Michael

Link to comment
Share on other sites

now the screen's completely black.

I haven't checked everything, but your first part may be okay-- the stuff you're doing during the "overscan" after setting TIM64T the first time. But you shouldn't be doing all that other stuff in the "vertical blank" period-- that stuff should be happening in the main portion that draws the picture. Move that stuff after the VSYNC so it's being done during your "active" loop, where you're drawing the background color. As long as VBLANK is turned on, there's no point trying to draw anything, because the picture is blanked at that time.

 

I have to crash now, too, otherwise I'd look at your code longer and see what else I could suggest.

 

Michael

Link to comment
Share on other sites

Hi, I normally just lurk in the programming forums because I find the discussions fascinating (even when they go over my head, which is most of the time... :roll: ). But, having had some training in [old-school] television werx, I believe I have something to contribute re: the "overscan" and "underscan" discussion.

 

...I have a personal issue with those terms the way they're used, because technically "overscan" means to draw the picture bigger than the viewable area of the TV screen, so the "overscanned area" is the part of the picture that can't be seen-- on all four sides, top, bottom, left, and right-- because it runs past the edges of the TV screen.

Well, technically, not exactly. The VCS programmer doesn't draw the picture bigger than the screen, any more than the broadcaster at the local TV station did. The reality of "drawing" the picture past the edges of the screen takes place entirely inside the TV. This was necessary because at the dawn of electronic television, the circuits inside TVs were less precise, and also subject to relatively wide variations from spec as a result of both heat buildup inside the set as all the tubes warmed up the cabinet, and gradual aging of parts over time. Thus TVs in the '50s and '60s had their pictures set deliberately with fairly generous overscan, so as parts succumbed to degradation from heat and age and gradually changed spec causing deformation of the picture, there would be "room" for the deformation (picture shifting position, shrinking horizontally or vertically, etc.) before the viewer noticed black bars on the edges where the beam was no longer even touching the screen.

 

Note that, from the beginning, in NTSC broadcasts there was picture information in the "overscan" areas. Depending on how much your TV overscanned the picture, you would see varying amounts of edge picture information.

 

Modern CRT TVs have much less overscan built-in, since modern electronics have higher tolerances (more precision and less prone to drifting off-spec). Non-CRT flat screen displays have almost no overscan at all; little or none in HD pictures I think, and a few lines at the top in NTSC mode to hide closed-captioning signals, etc.

 

SeaGtGruff, you may be saying, "Hey, isn't that just a longer version of what I said?" Well, maybe. Maybe you meant to say that, but I just noticed in your text the possibility of interpreting that you said "the Atari programmer or the VCS itself overscans the screen," when it's really the TV that overscans the screen. It may be a microscopic distinction, but an important one IMHO.

 

Here's where I think you're spot-on:

 

Atari programmers deliberately "underscan" the picture (draw it smaller than the TV screen) to make sure it's all visible, which is why you can see the blanking (or black "border" area) surrounding the game screen at the top, bottom, left, and right sides of the TV screen. And "vertical blank" includes *all* of the lines that are blanked, both at the bottom of the picture and at the top. So I personally avoid using those terms the way they're used by most Atari programmers-- but that's *me*. ;)...

This is exactly why producers of early TV shows, aware of this deliberate "overscan" defense mechanism built into TV sets of the time, made sure to film (or shoot with live camera) objects or talent so that nothing visually important strayed off center of the screen. This behavior is plainly obvious in credits, especially end credits, with all the smaller text of lesser contributors; the text will always be arranged center-screen, with vast amounts of unused space on the top, bottom and sides. It's just more visible today because there is far less (or no) overscan built into modern TVs.

 

Interestingly, since the VCS programmer is almost completely responsible for generating the TV image, he can build in as much or as little overscan as he wants. I've read programming posts about varying the number of VBLANK and/or overscan lines. If you need more screen real estate, reduce the number of VBLANK and or overscan, as long as it all adds up to 262 lines for an NTSC game. Similarly, if you need more game computation time, you can expand VBLANK and/or overscan to accomodate it, at the expense of visible screen space.

 

I wonder how much overscan can be eliminated. If a programmer had a game that needed very little computation time, and this game was assured to only be displayed on a non-overscan TV, he could theoretically devote almost all the screen to display and only a few lines to VBLANK and overscan.

 

Thoughts? Derision? (gulp) Flame? :)

 

-tet

Link to comment
Share on other sites

This is exactly why producers of early TV shows, aware of this deliberate "overscan" defense mechanism built into TV sets of the time, made sure to film (or shoot with live camera) objects or talent so that nothing visually important strayed off center of the screen.

 

I do some part-time camera work. The viewfinders are deliberately underscanned with markers indicating the 'title safe' area (inner) and the 'action safe' area (outer):

post-15728-127063871864_thumb.jpg

Link to comment
Share on other sites

Okay, update. Tried fixing more in my code. I added the player draw system to the main loop and added initializing of the playfield (I realized during Econ today that I'd left it out). I also moved the HorizPositioning subroutine to come before the graphics, just for good measure.

 

Anyways, here's what happens now:

 

whalemanscrewup2.png

 

I'm think I know what's wrong now but I'd really appreciate it if someone would double-check. I think some of my variables need more than one byte of RAM and I'm only allocating one byte for each of them. Would that cause this to happen?

 

Also, I think a less clunky player draw system is needed, as once I start adding the draw for the AI, I don't think it'll run quite well with two instances of that code going. Is there a subroutine in the likes of the horizontal motion subroutine I was given that would work?

 

Code is attached in the post below. Just need someone to double check my RAM allocation/usage. If that isn't the problem, I'd kindly ask someone to suggest another idea as to what's wrong now.

Edited by johnon
Link to comment
Share on other sites

The culprit isn't the animation counter. I just tried removing it entirely, and no dice. Same thing.

 

I guess I'll just wait for someone to double-check my RAM allocation/usage.

Edited by johnon
Link to comment
Share on other sites

I didn't look too close at your code, but I did see a few problems. Pointers require two bytes of RAM when using them in indirect Y mode. Say you have a pointer at $80, $80 will be the low address and $81 will be the high address. You may find it much easier to handle RAM like this:

 

   seg.u RAM
   org $0080

Variable        ds 1  ;one byte variable
Variable2       ds 1  ;one byte variable
Pointer         ds 2  ;two byte variable
                     ;etc...

   seg code
   org $F000

;;ROM code here

 

Also, it appears that you are writing to the graphics registers during overscan, in order to see the objects, you must do this during the kernel ;)

Link to comment
Share on other sites

I didn't look too close at your code, but I did see a few problems. Pointers require two bytes of RAM when using them in indirect Y mode. Say you have a pointer at $80, $80 will be the low address and $81 will be the high address. You may find it much easier to handle RAM like this:

 

(code)

 

Alright, I'll try fixing that and see what happens. What specifically needs how many bytes?

 

 

Also, it appears that you are writing to the graphics registers during overscan, in order to see the objects, you must do this during the kernel ;)

I fixed that in the last one...or at least should have fixed it, last I checked, which was in the post with just the code.

 

EDIT: Yep, I fixed it. It all comes after the StartOfFrame tag, which begins at the end of the TIM64T inside the OverscanLoop tag. :D

 

EDIT: After changing the variables, I'm seeing no difference. Here's how the variables look now:

 

; ---Variables-------------

SEG.U RAM

org $0080

PlayerYPosFromBot ds 1

PlayerCurrentHorizPos ds 1

VisiblePlayerLine ds 1

RabbitYPosFromBot ds 1

RabbitCurrentHorizPos ds 1

VisibleRabbitLine ds 1

WhaleLeftWPtr ds 2

WhaleRightWPtr ds 2

WhaleDownWPtr ds 2

WhaleUpWPtr ds 2

WhaleSLWPtr ds 2

WhaleSRWPtr ds 2

WhaleSDWPtr ds 2

WhaleSUWPtr ds 2

WhaleDeadWPtr ds 2

NumberOfAnimationFrames = #1

AnimationCounter ds 1

; -------------------------

SEG code

org $F000


Start

; insert rest of code here

Edited by johnon
Link to comment
Share on other sites

It is a good start, but there were quite a few misunderstandings in your code. I have attached a modified version, which lets you move a sprite around the screen. Hopefully this will let you make some more progress.

 

Chris

 

whalemansmash.zip

Thanks, Chris. I'll look through it and see what was wrong, etc. Mind if I post questions about changes here?

 

EDIT: Eh...on loadup, it does let you move the sprite around, but the sprite looks horribly transformed and there are only two colors alternating vertically across the screen rather than horizontal down it. >.>

 

EDIT3: Any kind of explanation on what the misunderstandings were would also help let me know where everything went wrong. I understand it was changed by yourself, but due to the massive modifications made, I've sort of lost any clue of what was originally wrong. Not to mention that the modifications have completely altered what was originally intended to happen...

Edited by johnon
Link to comment
Share on other sites

Alright, I'm starting to figure out what was changed. I just need to make the code more readable for myself. I'll see what I can do with what's there.

 

In the meantime, an explanation of what I did wrong in my code would be great for learning purposes. :D

Link to comment
Share on other sites

Hi, I normally just lurk in the programming forums because I find the discussions fascinating (even when they go over my head, which is most of the time... :roll: ). But, having had some training in [old-school] television werx, I believe I have something to contribute re: the "overscan" and "underscan" discussion.

 

...I have a personal issue with those terms the way they're used, because technically "overscan" means to draw the picture bigger than the viewable area of the TV screen, so the "overscanned area" is the part of the picture that can't be seen-- on all four sides, top, bottom, left, and right-- because it runs past the edges of the TV screen.

Well, technically, not exactly. The VCS programmer doesn't draw the picture bigger than the screen, any more than the broadcaster at the local TV station did.

I just noticed in your text the possibility of interpreting that you said "the Atari programmer or the VCS itself overscans the screen," when it's really the TV that overscans the screen. It may be a microscopic distinction, but an important one IMHO.

Right, I hadn't meant to imply that the *programmer* or the *Atari* is causing the overscan to happen, because it's the TV itself that's displaying less than the full picture signal and cropping the rest.

 

There's no way to make the 2600 do a horizontal overscan, because the horizontal blanking is done automatically by the TIA, and you absolutely *cannot* make the HBLANK period any shorter than 68 color clocks. On the other hand, you can turn VBLANK on and off on each line to make the HBLANK period *longer* than 68 color clocks, thus getting a narrower playfield than usual.

 

Vertically, you have full control, to the point of being able to royally screw up the picture by outputting far more or far less than 262 lines between each VSYNC. Assuming you've got a rock-steady frame of 262 lines, you can create a vertical overscan by decreasing the VBLANK period to get more active lines, such as by trying to draw 515 "active" lines instead of 480-to-485 active lines. But if, say, you had one of those nice old-timey TVs that let you adjust the vertical controls to scrunch the picture together, like in the opening images of "The Outer Limits," then it might be possible that what some programmer thought would be a deliberately overscanned game screen ends up being underscanned on your TV! :D

 

Anyway, you're right; overscanning is (mostly) the TV's fault, not the Atari's-- except for the occasional crazy programmer. ;)

 

The best way to define it is that overscanning is when the picture or "active signal" is bigger than the viewing area of the screen, *regardless* of whether it's the fault of the signal generator (TV camera, Atari, etc.), the signal receiver (TV set, monitor, etc.), or both.

 

The point I was trying to make is that, since the "overscan area" is actually the part of the picture that's being drawn "offscreen," and since the black area that's visible at the bottom edge of the TV screen, just below the game screen, is actually caused by underscanning rather than overscanning, it strikes me as 180 degrees contrary to the meaning of "overscan" to use that term for the portion of the VBLANK routine that's at the bottom of the TV screen. And since the "bottom border" or so-called "overscan" (as used by Atarians) is vertical blanking, too, it doesn't seem right to use the term "vertical blank" for just the portion of the VBLANK routine that's at the top of the screen. "[Vertical] front porch" and "[vertical] back porch" might sound funny, but I think they're more technically-correct terms to apply to those two routines, since the "bottom border" or so-called "overscan" is just a vertical front porch that's been deliberately increased to about 30 lines or so (I think the standard for NTSC is about 3 lines). Likewise, the "top border" or so-called "vertical blank" is just a vertical back porch that's been deliberately increased to about 37 lines or so (I think the standard for NTSC is about 10 or 12 lines, depending on which documentation you're looking at).

 

It would make more sense to use the term "underscan area" or "underscan routine" to refer to the VBLANK lines at the bottom of the screen, although that term could just as easily apply to the VBLANK lines at the top of the screen. But at least it would make more sense than calling something "overscan" when it's really the result of a deliberate "underscan."

 

Here's where I think you're spot-on:

 

Atari programmers deliberately "underscan" the picture (draw it smaller than the TV screen) to make sure it's all visible, which is why you can see the blanking (or black "border" area) surrounding the game screen at the top, bottom, left, and right sides of the TV screen. And "vertical blank" includes *all* of the lines that are blanked, both at the bottom of the picture and at the top.

Pity the poor schmoe whose TV is so crappy that the 2600's deliberately-reduced-in-size game screen ends up being overscanned *anyway*! ;)

 

This is exactly why producers of early TV shows, aware of this deliberate "overscan" defense mechanism built into TV sets of the time, made sure to film (or shoot with live camera) objects or talent so that nothing visually important strayed off center of the screen. This behavior is plainly obvious in credits, especially end credits, with all the smaller text of lesser contributors; the text will always be arranged center-screen, with vast amounts of unused space on the top, bottom and sides. It's just more visible today because there is far less (or no) overscan built into modern TVs.

Yes, the "safe" areas. There are two kinds-- "action safe" and "title safe." If I remember correctly, "action safe" allows for an overscan that's 5% of the picture on all four edges, or tries to keep the action within the central 90% in the vertical dimension (5% + 90% + 5% = 100%), and the central 90% in the horizontal direction (5% + 90% + 5%). "Title safe" allows for even more overscan-- I think it's 10% in all directions, or the central 80% in the vertical and horizontal directions (10% + 80% + 10%).

 

If we assume that the standard NTSC picture has an active area of about 240 lines (non-interlaced), that gives us an "action safe" area of 216 lines, and a "title safe" area of... drum roll, please... 192 lines! It's just icing on the cake that 192 scan lines is perfect for displaying 24 lines of 8-pixel-high character text on a computer screen. Some computers had 25 lines of text (200 scan lines), and we could certainly do that on the Atari-- but 24 is more highly divisible than 25 is.

 

Horizontal resolution is another animal. If we go by the color subcarrier cycles, there are 227.5 color clocks per line in a normal "old-timey" TV signal, although the Atari has 228 color clocks. The horizontal resolution of the TV picture might be higher than that, because you can display alternating black and white vertical lines across the screen using the crests and troughs of the color signal (or "half-clocks"), which is how the Atari 800, 5200, and 7800 can display 320 pixels using 160 color clocks. So in theory (ignoring the need for HBLANK and HSYNC), 227.5 color clocks should give use a maximum horizontal resolution of 455 pixels. But in reality the horizontal resolution is affected by the quality of the camera or other device that captured/recorded/replayed the incoming video signal, the quality of the incoming signal itself, and the quality of the TV receiver that's displaying the picture. For the 2600, we might as well just use 228 as the magic number, since that's how many color clocks there are, and the 2600 can't do half-clock pixels as the 800, 5200, or 7800 can.

 

The old NTSC signal had about 10.9 microseconds of HBLANK, and about 52.6 microseconds of active video on each line, or a total of about 63.5 microseconds for the total scan line. I think those numbers can vary a little bit depending on the video standard used. The NTSC line length of 227.5 color clocks is really 63.555 repeating 5 microseconds long, and the Atari's 228-clock line is 63.6952380952380 repeating 952380 microseconds long (due to the extra half-clock). But the other two numbers-- 10.9 (HBLANK) and 52.6 (active)-- add up to 63.5, so we'll just use that. This means the HBLANK period is about 17.165% (or 10.9 / 63.5) of the line, and the active period is about 82.835% (or 52.6 / 63.5) of the line, giving us a maximum of about 188.45 color clocks for the active portion of the line (227.5 * 82.835%). The "action safe" area would be about 169.60 color clocks, and the "title safe" area would be about 150.76 color clocks. The Atari's active screen width-- 160 color clocks-- is about 84.90%, or about midway between "action safe" and "title safe." :)

 

Interestingly, since the VCS programmer is almost completely responsible for generating the TV image, he can build in as much or as little overscan as he wants. I've read programming posts about varying the number of VBLANK and/or overscan lines. If you need more screen real estate, reduce the number of VBLANK and or overscan, as long as it all adds up to 262 lines for an NTSC game. Similarly, if you need more game computation time, you can expand VBLANK and/or overscan to accomodate it, at the expense of visible screen space.

Yeah, like I said, you can decrease (or increase) the number of VBLANK lines at the top and/or bottom of the screen, although you can't decrease the HBLANK period to get a wider game screen-- only make it narrower if you really want to.

 

I wonder how much overscan can be eliminated. If a programmer had a game that needed very little computation time, and this game was assured to only be displayed on a non-overscan TV, he could theoretically devote almost all the screen to display and only a few lines to VBLANK and overscan.

When I was programming the (in)famous "ET Book Cart" for Atari Charles, I wanted to put as many lines of text on the screen as I could, but I was also concerned about some people not being able to see the text at the very top or bottom. Right now I can't remember what I finally settled on, but I think it was either a multiple of 12-- namely, either 216 ("action safe") or 204 (halfway between "action safe" and "title safe")-- or it had an extra 4 lines (i.e., 208 lines in all). That's because (if I remember correctly) the characters were 8 lines tall, but I had 4 blank lines between each row (call it 12 lines per character), with an extra 4 lines to center things:

 

4 blank lines

8 lines for text

4 blank lines

8 lines for text

4 blank lines

8 lines for text

...

4 blank lines

8 lines for text

4 blank lines

 

= (4 + 8) * X + 4 = 12 X + 4, where X is the number of text rows. So

 

16 rows would be 12 * 16 + 4 = 196 lines,

17 rows would be 12 * 17 + 4 = 208 lines, and

18 rows would be 12 * 18 + 4 = 220 lines, etc.

 

As I recall, I was afraid to try for 220 lines, so I went with 208 lines because it's between the "title safe" and "action safe" values. The only reason this was feasible was because a text screen requires very little "busy work" for calculations between frames, and all of the real "grunt work" occurs during the 4 lines before the row of text, and within the row while the text is being drawn.

 

I thought my (no-longer-all-that-new) 1080p HD LCD-TV didn't do *any* overscanning (except for when using zoom and such). But I created a little 2600 program to draw a screen display that lets me count how many lines are visible, as well as figure out *which* lines are being displayed. If I've figured things correctly, it turns out my set actually displays only 226.5 non-interlaced or 453 interlaced lines in the 480i mode. I believe they are lines 30 through 255 on the first field (226 lines), and lines 292 through 518 on the second field (227 lines). I should be ecstatic, because that's about 94%, more than the "title safe" area-- but I can't help feeling sort of bummed out about it! ;)

 

Michael

 

Edit 1: 180 degrees contrary, not 180% contrary. D'oh!

 

Edit 2: Undoing the 8). (the forum software strikes again!)

Edited by SeaGtGruff
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...