-
Content Count
5,587 -
Joined
-
Last visited
-
Days Won
2
Content Type
Profiles
Member Map
Forums
Blogs
Gallery
Calendar
Store
Everything posted by SeaGtGruff
-
Glad to hear it! Working with playfield text can be tricky. To stop the letters from flashing, you're going to have to find out where the code is that's doing it, and figure out how to change it without messing up anything. When I get home later I'll take a look at it. I'm not familiar with ShowGfx, so I can't really compare them, but I know from experience with other types of programs that one program can be better than another in certain ways, and vice versa. In other words, each program may have its own strengths and weaknesses. ShowGfx may be superior to Hack-O-Matic II in some ways, and inferior in other ways. Likewise, Hack-O-Matic II may be inferior to other programs in some ways. Sometimes I like to "collect" different programs so I can jump from one to another and use the one that's best for the job. But I've never tried to hack games, so I haven't ever collected different hacking utilities, and the only reason I have Hack-O-Matic II is because someone had asked about hacking colors and I was trying to answer them, so I downloaded Hack-O-Matic II to help me better relate to what they were up against. Michael Rideout
-
That's weird, I can't see the first two pictures, so I'll repost them. This is what they were supposed to look like: (Hope they show up this time.) Michael Rideout
-
They're drawn with the playfield. Using Hack-O-Matic II, it looks like they start at around 0b88. Michael Rideout 972589[/snapback] Thanks, now that I know where they are any advice on changing the lettering? Every time I make a few changes the whole program stops workin. Thanks, Tim 972925[/snapback] Hmm, that shouldn't happen, so you must be changing more than just the bytes for the title letters? I don't have SHOWGFX and am not familiar with it, but I have Hack-O-Matic II. If you change just the bytes for the title letters, the game should still work, just with a different-looking title screen. But the thing is, playfield graphics can be difficult to use for text displays, because (1) the letters tend to look big and blocky-- although you can still attain reasonably decent results if you try to make the letters a bit rounded (see below)-- but more importantly, (2) you have to understand how the bytes are being used. Once you understand that, you are closer to successfully hacking the playfield text to say something different. Okay, here is what the title screen looks like: And here's the start of the relevant section of code in Hack-O-Matic II: (By the way, I was wrong before-- it actually starts at 0b7e, not 0b88.) There are a number of important points that you need to understand about how the bytes are being used for the playfield: (1) The bytes-- or the data for the letters-- are stored "upside down," not just for each letter, but for the three rows of letters. In other words, the data for the third row of letters begin at 0b7e, with the byte for the last scan line of row three given first, then the byte for the next-to-last scan line of row three, etc. (2) The data for each row of letters must be divided up into several sections, due to the way the playfield works. The playfield has only two-and-a-half bytes(!), so the programmer must move the data into those two-and-a-half bytes twice for each scan line-- first for the left half of the screen, and then for the right half of the screen. There are two ways the playfield can be drawn-- normally, where the right side is an exact duplicate of the left side; or reflected, where the right side is a mirror image of the left side. In this game, the title is drawn using the normal method, so the data looks like this: half a byte, one whole byte, one whole byte, half a byte, one whole byte, one whole byte. Of course, since the programmer is changing the bytes before the right half of the screen is drawn, the right half is different than the left half (which is an "asymmetrical" playfield, although it's still drawn using the normal playfield mode). So because of the way the playfield is being drawn, -- the data for the first four columns of playfield pixels are 0b7e through 0b8c; -- the data for the next eight columns of playfield pixels are 0b8d through 0b9b; -- the data for the next eight columns of playfield pixels are 0b9c through 0baa; -- the data for the next four columns of playfield pixels are 0bab through 0bb9; -- the data for the next eight columns of playfield pixels are 0bba through 0bc8; -- the data for the last eight columns of playfield pixels are 0bc9 through 0bd7. (3) However, we can't store half a byte-- unless we store two halves of a byte in one whole byte and then shift the data as needed to get the desired half, which the programmer(s) didn't do-- so the data at 0b7e through 0b8c, and 0bab through 0bb9, are stored as whole bytes, even though only half of each of those bytes are actually being used. As you can see from the picture above, the left half (or high nibble) of each byte is used, and the right half (or low nibble) is left blank. (4) Due to the way the 2600 reads the bytes as it draws the playfield, some of the bytes have to be reversed-- that is, the 2600 reads them from right-to-left instead or from left-to-right, as follows: -- the byte for the first four pixels is read right-to-left (backwards); -- the byte for the next eight pixels is read left-to-right (normally); -- the byte for the next eight pixels is read right-to-left (backwards); -- the byte for the next four pixels is read right-to-left (backwards); -- the byte for the next eight pixels is read left-to-right (normally); -- the byte for the next eight pixels is read right-to-left (backwards). (5) To save ROM, the programmer(s) didn't try to map the entire playfield, just the three rows where the letters of the title are being drawn. In fact, the blank spaces or scan lines between the three rows of text aren't even being stored. This means you can redefine the shapes of the letters by hacking the corresponding bytes, but the new text is limited to three rows of letters (or other shapes) that are five lines tall, and you can't extend the new letters into the blank scan lines that are above, between, and below those three rows of text. I realize that this is all a bit much to absorb, so I've chopped out the blank lines of the title screen with a paint program, and changed the background and foreground colors to emphasize the way the screen is divided up into six vertical strips: The colors make it kind of hard to read the text, but I hope you can see how there are six areas going from left to right. I've drawn arrows under each of these six areas, pointing either right-to-left or left-to-right to indicate the direction in which the Atari is reading the bytes. To make things even clearer, let's look at how each area corresponds to the bytes in the program code: I used a paint program to color the Hack-O-Matic II screens, and colored the text in the screenshots to match, to try to help you see how the data in the program code corresponds to the text in the screen display. As you can see, the data is stored upside-down, the data is stored backwards for some bytes, and the data for some bytes uses only the left (high) half of the byte. So if you want to hack the title text to say something else, you're going to have to be careful about which bytes you change, do everything upside-down, do most of it backwards, etc. You might want to use a piece of graph paper, and divide it up into sections to match the way it's divided up in memory, then create the new text on the graph paper and use it to help you hack the bytes accordingly. As I mentioned above, you can create better-looking text with playfield pixels if you try to round the letters. Unfortunately, you can't do that in this game, due to the way it stores the data, because each byte is actually used to draw several scan lines (to help save ROM space). Anyway, the screenshot below shows a title screen that I made for a game I started to write (but then put aside), and you can see how the letters look a little better because of the way I made the letters a little more rounded. Good luck in your hacking, and I hope this post has helped you understand how "The Texas Chainsaw Massacre" title screen is stored. Michael Rideout
-
It might be, if there are in fact bricks in both of those spots. What I would suggest doing would be to determine the existence of brick/wall in the four corners of the ball; depending upon the position of the ball, this may require looking at one, two, or four bricks. If the number of bricks present in the top two corners exceeds that in the bottom, move the ball downward. If the number of bricks present in the bottom two exceeds that in the top, move the ball upward. If the number of bricks present in the left two exceeds that in the right, move the ball rightward. If the number of bricks present in the right two exceeds that in the left, move the ball leftward. If all four corners are occupied by "brick", set X direction toward the center of the screen and set Y direction to "down" (shouldn't happen, but that's probably the best course of action). Doing things this way will allow for effective handling of all cases where the ball hits bricks; if it hits the left side of a brick while going diagonally upward, it will bounce off but continue its upward path. 972609[/snapback] Yes, that's a good point about hitting the side of a brick and continuing up (or down). I'd thought about that as well last night, but forgot to mention it. As for checking the four corners of the ball, that's only necessary if it's potentially hitting three bricks at once. Most of the time it will be hitting only one or two bricks. I'd started working on some routines to handle these cases, but wasn't happy with the way they were going (I wanted to find a way to consolidate or simplify them), and I removed the code before I posted it because I wasn't sure how Luigi301 wanted the ball and bricks to behave. After all, my vision of how the game "should" work may be very different from what he has in mind. But I'll keep working on it and post my solutions if he wants, and anyone else can optimize the code for ROM space and/or machine cycles. Michael Rideout
-
I used HexView to look at the 4K .bin, it says "PJOE GAUCHER LOUIS MARBEL" near the end of the code (but maybe the first P isn't part of the names?). The 8K .bin says the same thing. Michael Rideout
-
They're drawn with the playfield. Using Hack-O-Matic II, it looks like they start at around 0b88. Michael Rideout
-
Well, now I'm not checking p against j so it's not bigger than q! I'm not sure what you're refering to, I saw no J in your last posted code. Was that something in your earlier posted code? I removed the variables that were used to save the player0x and player1x values since there's no real need for them, the bB variables keep their values (unlike registers on a 2600 or 800) so you can just use them instead of having extra variables for them. So instead I added variables for the extreme "good" left and right positions-- p0_l_limit, p0_r_limit (player0 left and right limits), and p1_l_limit, p1_r_limit (player1 left and right limits), which have to be a little bit different depending on the size of the players (i.e., difficulty settings). I wasn't finished with the routine, which is why it's horribly broken. The hardest part about getting a brickrow value is turning bally into a value that corresponds to a row number. Also, the ball going off the bottom isn't quite working yet. bally eventually wraps and the ball appears at the top of the screen. Yes, I gathered that you weren't finished with that part, so I started to work on it for you, but then I thought, "Whoa, you aren't sure how he wants things to work!" so I took it out (but I saved it first so I can continue on it if you'd like). For example, when the ball goes past the paddle and leaves the screen, what do you want to have happen? My guess was that you want the player with that paddle to lose their "turn," meaning that ball is gone and the other player starts a new ball into play. For that, you'd need another start_ball routine (e.g., p0_start_ball for when player0 starts the ball, and p1_start_ball for when player1 starts it). The conversion from the ball coordinates to the playfield coordinates shouldn't be too bad, except for handling when the ball is colliding with two or three bricks at the same time. I temporarily added some code to freeze the ball on collision, and display its coordinates in the score, which helped me find the following values: ballx = 31 means ball is hitting the left wall and brick 0 simultaneously. ballx = 32 through 34 means the ball is hitting just brick 0. ballx = 35 means the ball is hitting bricks 0 and 1 simultaneously. ballx = 36 through 38 means the ball is hitting just brick 1. ballx = 39 means the ball is hitting bricks 1 and 2 simultaneously. etc. I modified the calculation accordingly, first I subtract 32 from ballx to get brickx, then I divide brickx by 4 (you were dividing by 4 first, then subtracting 8, which is more or less the same thing, but I like the subtract-then-divide better). My thinking was that if the ball is colliding with two or three bricks simultaneously, then check the ball's direction to see which brick to remove. For example, if the ball is moving left, and hits both brick 3 and brick 4, then remove brick 4, but if brick 4 has already been removed then remove brick 3. Or, if the ball is moving right and hits both brick 3 and brick 4, then remove brick 3 if it hasn't already been removed, otherwise remove brick 4. I'm not certain of the bally values yet, but I think they're as follows: bally = 31 means the ball is hitting "air" and row 0 (pfrow 4) simultaneously. bally = 32 through 38 means the ball is hitting just row 0 (pfrow 4). bally = 39 means the ball is hitting rows 0 and 1 (pfrows 4 and 5) simultaneously. bally = 40 through 46 means the ball is hitting just row 1 (pfrow 5). bally = 47 means the ball is hitting rows 1 and 2 (pfrows 5 and 6) simultaneously. etc. So the quickie conversion would be bricky=bricky/8 (so you'll have to add back the "include div_mul.asm" which I took out). But in both cases, brickx and bricky, you need to check whether the ball is colliding with just one brick, or two or three bricks, and then figure out which brick to remove depending on which bricks have already been removed (and perhaps also which way the ball is moving). For example, if ballx=38 and bally=63, then the ball is hitting just brickx=0 and bricky=7, so there's no question-- remove that brick, it's the only one the ball can be hitting. But if ballx=39 and bally=63, then the ball is hitting brickx=0 or 1 and bricky=7, so you don't know whether the ball is hitting both bricks (i.e., if neither one has been removed yet), or just one (i.e., if one of them has already been removed), until you check them with pfread. Or, if ballx=39 and bally=47, then the ball is hitting as many as three bricks at the same time-- brickx=0 or 1, and bricky=5 or 6. You know it can't be hitting all four bricks, because at least one of them must have already been removed in order for the ball to collide with any remaining bricks at just that spot, but since you don't know which brick has already been removed, you have to assume that all four are still there, and check them one by one depending on the ball's movement. For example, if the ball is moving down and left, then remove brickx=1,bricky=5 if it hasn't already been removed, else remove brickx=0,bricky=5 if it hasn't already been removed, else remove brickx=1,bricky=6 if it hasn't already been removed, else remove brickx=0,bricky=6. Or, if the ball is moving down and right, then remove brickx=0,bricky=5 if it hasn't already been removed, else remove brickx=1,bricky=5 if it hasn't already been removed, else remove brickx=0,bricky=6 if it hasn't already been removed, else remove brickx=1,bricky=6. Or, if the ball is moving up and left, then remove brickx=1,bricky=6 if it hasn't already been removed, else remove brickx=0,bricky=6 if it hasn't already been removed, else remove brickx=1,bricky=5 if it hasn't already been removed, else remove brickx=0,bricky=5. Or, if the ball is moving up and right, then remove brickx=0,bricky=6 if it hasn't already been removed, else remove brickx=1,bricky=6 if it hasn't already been removed, else remove brickx=0,bricky=5 if it hasn't already been removed, else remove brickx=1,bricky=5. In other words, you're always removing the first brick that the ball is hitting. For example, if it's hitting brickx=0 and 1 at the same time, then it's hitting brickx=1 first if it's moving left, and hitting brickx=0 first if it's moving right. 600 bytes saved? Shows how bloated my code is. Not necessarily. The main savings came from consolidating make_screen so the four rows could be drawn with a FOR..NEXT loop, which I did by making the bricks variables into an array. I'm not sure yet (haven't tried it), but further savings may be possible by writing directly to the playfield instead of using pfhline. It would certainly save time cycles at least. A while back I worked out how to store the playfield as data, and move it directly to the playfield array, without having to use the pf draw routines. In some cases it uses more ROM (if only a few pf draws are needed to draw the screen), but it almost always saves a whole lot of machine cycles. I'm posting an example that draws a purple castle as in Adventure, to illustrate the process. I'm posting the .asm and .bin files, too, because I had temporarily modified the score digits to spell out "Reventure" (but there's a timing issue in the 6-digit display that causes the "broken" letter in the second position-- the last column of the first digit gets changed to the last column of the third digit because the player0 data gets moved a hair too soon), and you won't be able to see that if you compile the .bas file yourself without using the modified score digits. Michael Rideout test.zip
-
Okay, here's my "cleaned up" version, which does more or less the same things that your original code does. (Paddle 0 is getting positioned a little to the right of paddle 1, even though they have the same X position, don't know why.) I added some DIMs so that all variables have meaningful names, and I made a few other changes, so you might want to compare it closely to your original code to see if there's anything you want to change back. As it is, there are a few problems with the code that you need to work out, mostly dealing with how the ball hits the bricks. For one thing, your routine to turn off the bricks when they're hit is turning off only the bricks in row 7. This can be fixed by calculating the bricky position in a similar manner to the way brickx is calculated. Also, it's possible for the ball to hit more than one brick at once, which is why the bricks in the middle don't get turned off when the ball keeps hitting them (the calculation to get the equivalent brick position keeps returning the brick that's already been turned off, since the ballx position straddles two bricks). Also, if the ball hits the side walls without actually hitting a brick, you want to bounce it but not turn off any bricks, so your "hit_something" routine needs to check for that. And I figure you might want to modify the way the ball bounces so it doesn't always go back the way it came (e.g., after the first hit, bounce it down to the left instead of back down to the right). I actually started to add code for these things, but I've removed it so I can post my initial "clean up" version since I don't know how you want the ball and bricks to behave in those situations. Also, I fixed the positioning of paddle 1, which wasn't being displayed in your original code, so I hope that was okay (maybe you had meant to remove it)? And I added movement for the paddles by reading the joysticks. However, in doing so I discovered that bB has no functions for joystick 1! So I added joy1up, joy1down, joy1left, joy1right, and joy1fire to bB, but then I decided to remark out the lines for joystick 1 for the moment. In any case, I'm posting the include file that has the joystick 1 functions added to it, but I can't upload a file with the .asm extension, so I renamed it to a .bas extension, and you'll need to rename it back to the .asm extension before you can use it. Let me know what you think. Michael Rideout PS -- The good news is that I redesigned your make_screen routine in a way that uses up less ROM, so there's more room for additional levels-- although the logic to handle the ball/brick problems mentioned above will eat up most of the saved ROM, if not more than what was saved. breakout.bas std_routines.bas
-
Well, I could try to clean up the version I started, and post it for you, but it sounds like you've already added a lot more to the game. If you want to post an updated version of the source, I could un-spaghetti-fy it for you. Michael Rideout
-
Wow! I think I'm in the first two pictures, which show the games set up with the TV sets. I have my back to the camera, and in both pictures I'm the guy directly to the left of the lady who's walking around. Michael Rideout
-
Did you see my reply from Oct. 21? The problem was being caused by a reference to a line number that didn't exist. So in making other changes, you probably fixed the line number problem without realizing it! Michael Rideout 970161[/snapback] I fixed that and it still didn't work, I figured out I was checking variable M, which I never set. 970421[/snapback] The line number problem is what was causing the compile error, but you're right that the program still wouldn't run (even though it would at least compile) after the line number was fixed. I had looked at your code, and tried to reorganize it or clean it up, but I was kind of busy with other things and didn't have time to figure out everything you were doing, so I put it aside. I'm glad you got it working again. I can post my unfinished version of the reorganized code if you want, keeping in mind that it doesn't run correctly. Michael Rideout
-
Did you see my reply from Oct. 21? The problem was being caused by a reference to a line number that didn't exist. So in making other changes, you probably fixed the line number problem without realizing it! Michael Rideout 970161[/snapback] Hey SeaGt... I guess I'm a little slow. It took me until now to realize that your avatar is the Swordquest Fireworld chalice, and that you won it back in '84. http://www.geocities.com/TimesSquare/Lair/9260/sqfw.html Do you still have the chalice? 970334[/snapback] Yes, I still have it. When I joined AtariAge, I couldn't think of anything else to use as an avatar. Michael Rideout
-
Did you see my reply from Oct. 21? The problem was being caused by a reference to a line number that didn't exist. So in making other changes, you probably fixed the line number problem without realizing it! Michael Rideout
-
Maybe thats where he came up with the BSOD. 967591[/snapback] Except the Atari BSOD has a nicer shade of blue... 967663[/snapback] Hmm, I thought there was an interesting sense of color familiarity in the BSOD! By the way, Foebane, I like your avatar-- it's an image from TMCOG, right? I have almost all of the series on tape, except I screwed up and missed an episode or three somewhere near the end. :-( Michael Rideout
-
Maybe you should remember your own posts. 966511[/snapback] The thing about any flickering technique is that... well... it flickers! So even though these demos and games that use flickering are extremely impressive, I think it's best to keep the number of flickered frames to a minimum (i.e., two rather than three), and to keep the amount of flickered colors on the screen to a minimum, otherwise the results can be too distracting to the viewer/player. As for "discovering" techniques that other people have already used, well, it's happened to me in both directions. I was experimenting with "Super IRG" mode some ~10 years before it was apparently given that name, but IIRC my inspiration for it came from something I'd read in "Mapping the Atari," so undoubtedly there were other people out there who'd done the same thing before I tried it; and since I didn't write an article about it or give it a name, I can't quarrel with anyone else for "discovering" and "naming" it several years after I used it privately. But I do know that when I "discovered" it for myself, I kept thinking "Why isn't anyone writing games that use this technique?!?" I never wrote/finished one, so more power to anyone who did! I have a bit of a quandry with this right now, because I've just spent the last few nights working on graphics for a "Dragon Warrior" demonstration that relies on the "flicker/dither"... harumph, I mean "Super IRG"-- technique to get a pretty decent representation of a "Dragon Warrior" screen (on the 8-bit emulator), but really, what's the point? What I mean is, I can finish it and post it to show that a fairly accurate A8 port of "Dragon Warrior" is possible, but if it could never be published anyway, then it would be far more productive to use the technique to create an original game. I've been working in Paint to draw the screen, which I'm now coding for the A8, but even though the picture wasn't done directly on the A8, it should still look pretty close on it, because I picked and mixed the colors on an A8 emulator and saved the screenshot in interlaced mode, then used those color values in the Paint program... although of course it could make a big difference what the palette settings are, and the picture won't look the same on a real Atari as on an emulator, because the colors mix a bit differently. Still, I'm going to post the Paint picture so people can see what I've done. The screen uses a 13x13 map, with each "block" (2x2 characters on a Nintendo) being drawn as a 3x2 block on the Atari, to get 12 pixels across and 16 down in each block-- really 13 and 1/3 blocks across, and 26 lines of GRAPHICS 12 characters to get 13 blocks down. For the blocks that have animated characters/sprites in them, I ended up using a solid background rather than trying to show the terrain behind/underneath the sprite, since my picture assumes that the P/M graphics will be used at quad-width to get a sixth "underlay" color which will replace pixel color "00" in those blocks where the "00" color is from the P/M graphics rather than from SETCOLOR 4. And since each "block" is only 12 pixels across rather than 16, my A8 conversion isn't exactly the same as the Nintendo version. But these pictures should still give an idea of what could be accomplished with flicker/dither. Michael Rideout DragonWarrior_0000.bmp
-
Recommended study references for A8 game coding
SeaGtGruff replied to birdie3's topic in Atari 5200 / 8-bit Programming
Should you learn BASIC first? Well, BASIC will let you get started right away, so you can play around with the graphics to see how the different modes work, etc. But BASIC doesn't let you control the Atari the way assembly does. On the other hand, assembly isn't as immediate as BASIC is. So each has its own strengths and weaknesses. But without a doubt, assembly is probably what you'll want to end up programming in, because it's so much more powerful than BASIC. This doesn't mean you shouldn't start with BASIC, though, and there's no reason why you can't learn both at the same time. In fact, you can write assembly routines and call them from within BASIC programs if you want. If you don't know much about the Atari 800/XL/XE, you'll definitely want to get a good book about its memory locations, such as "Mapping the Atari." It might not help you get started with programming the Atari, but it will be an invaluable reference that you'll turn to again and again as you learn to program the Atari. Also, it makes a difference whether or not you already know anything about programming in general (i.e., on any computer or in any language, not just on the Atari in particular). For example, the Compute! books on Atari are okay for learning about different tricks, but you'll get more out of them if you already know how to program. So if you're just getting started in programming, any good beginner's textbook about whichever language you're interested in-- BASIC, assembly, Forth, C, etc.-- might be helpful, whether or not it specifically deals with the Atari. Of course, if you're learning assembly, then you'll want to get a book about 6502 assembly, since that's what the Atari uses. And if you're learning from a book that doesn't deal specifically with the Atari or its version of a given language, then you might need to compensate for any differences between the version of the language that's described in the book versus the version that's available for the Atari (e.g., Deep Blue C doesn't have everything that C++ does). Aside from that, the best thing to do is to have a pretty clear idea of what you want to accomplish in a game, and be familiar enough with the Atari's features and capabilities to know if or how you can make it happen on the Atari. That is to say, you might have a fabulous game idea, but it might not be possible to do it on the Atari in the exact manner that you've envisioned, so if you're familiar with what the Atari can do (including advanced techniques that let you push the Atari past its usual limitations), then you'll be able to rethink your game vision to reshape it into a more workable plan. Above all, I recommend just tinkering with little snippets of code to experiment with different features and techniques. Some of the books may help with that, but nothing beats just pure imagination. For instance, back in the '80s I experimented with the "flicker/dither" technique, and I created simple displays in GRAPHICS 12 that expanded the number of available colors by blending the five colors that are available in GRAPHICS 12. If I remember correctly, my inspiration for this was something I'd read in "Mapping the Atari." I started designing some graphics for an adventure game using this technique, but then my disk drive broke and I put the Atari aside so I could focus more on the Amiga. Just recently, I found out that someone made a game using that same technique, in 1998 I think, and he gave the "new" graphics mode the name of "Super IRG"! So you shouldn't stick to just what the books say, but try to think of how to combine different features or techniques in ways that might not be specifically described or demonstrated in the books. Chances are, there are other people out there who have already tried it, or are just beginning to try it, so you might be able to get pointers or suggestions from them. (I wish I'd had access to a forum like AtariAge back when I was first learning about the Atari!) Out of curiosity, what sorts of games are you interested in programming, and which books have you been reading about the Atari? Michael Rideout -
Hi, Andrew! Are you talking about flickering three frames together-- one with red dithering, one with blue dithering, and one with blue dithering? If so, I've heard of that idea before, but have never tried it or seen it in action. I'll do a search for your chronocolour demos, they sound intriguing. Michael Rideout
-
What you are describing is artifacting, a phenomenon which may be used when the dot clock is a multiple of the chroma clock (2x on the Atari 8-bits or the 7800; 2x or 4x on the Apple) and which is nothing but trouble on machines where color is line-synchronized but the dot rate doesn't match chroma (e.g. old Commodore 64's). On the 2x machines/modes, even pixels will appear different colors from odd pixels. On an Atari machine that can show 4 colors in 320-dot mode, it is entirely practical to use artifacting to generate 16 colors. There is some flexibility in choosing what those 16 colors are, but not total. Basically, just pick different combinations of four colors and see what combinations of 16 colors they yield. 964068[/snapback] I'm not talking about artifacting in GRAPHICS 0, where each pixel is only half of a color clock. I mean dithering in a high-res GRAPHICS mode (e.g., GRAPHICS 15) where each pixel is a full color clock. Several years ago, I started working on the graphics for an adventure game, using brown, white, yellow, red, and blue as the basic colors in GRAPHICS 12 (red for bits 11 with normal characters, and blue for bits 11 with inverse characters). By choosing the right hues and luminances for the colors, I could get a pretty decent light green (blue and yellow) and dark green (blue and brown) to create, for example, a landscape of trees-- light green for the grass, dark green for the foliage on the trees, and of course brown for the tree trunks. Dithering can be used with many patterns, but to get the appearance of new solid colors that are mixtures of two real colors, the pattern should be a checkerboard, with the colors in the pattern being alternated from one frame to the next (correct technical term should be field, but if the picture is noninterlaced, then each field is a frame). Without flickering between alternating color patterns, you just get a checkerboard dither of two colors, as in the standard paint programs for the Atari. You can also make checkerboard patterns between a real color and a mixed color, which looks like the checkerboard dither of a standard paint program except one of the colors comes from a mixture. Or you can create dithers where the dots have a 75%-25% mixture rather than a 50%-50% mixture. So for example, if you start with yellow and red and your two real colors, you could get seven mixtures between yellow and red, with the middle mixture being a "solid" color: 100% yellow 75% yellow, 25% orange 50% yellow, 50% orange 25% yellow, 75% orange 100% orange (yellow and red mixed by dithering and flickering) 25% red, 75% orange 50% red, 50% orange 75% red, 25% orange 100% red I used to have a demo screen that I made on the XL/XE which displayed a color wheel with real colors, "solid" mixtures, and dithered patterns between the "solid" mixtures and real colors. I programmed it so I could turn the flickering on or off by pressing a certain key, and the difference between the two was nothing short of dramatic. With no flickering, the same color mixtures listed above would be: 100% yellow 87.5% yellow, 12.5% red 75% yellow, 25% red 62.5% yellow, 37.5% red 50% yellow, 50% red 37.5% yellow, 62.5% red 25% yellow, 75% red 12.5% yellow, 87.5% red 100% red On a TV, there may be some artifacting involved which creates "color bleeding" (don't know what else to call it) that helps to further blend the colors when using a dithered pattern in a high-res color mode, but I'm not talking about GRAPHICS 0 artifacting, and I haven't heard anyone use the term "artifacting" when describing the dithered checkerboard pattern that is commonly used in Atari paint programs to mix two colors together. I experimented with artifacting in GRAPHICS 0 and GRAPHICS 8, but I was never able to create the "16 colors" that I had read about, just four artifacted colors which could then be dithered together. These sorts of techniques are very easy to implement on an 8-bit Atari if you trick the Atari into thinking it's using a different GRAPHICS mode. For example, switch to GRAPHICS 8, POKE 87 with 9, and you can PLOT and DRAWTO using COLOR values from 0 to 15, the so-called "16 colors" that you get from artifacting. What you actually get are 16 combinations of four artifacted colors, but you can combine this with flickering to make the mixtures look more "solid." However, as long as you're just getting four artifacted colors that are being mixed together, it makes more sense to me to use four real colors in a high-res color mode. On the other hand, the artifacted colors are not the same as the Atari's real colors, and by using different hues and luminances with GRAPHICS 8 you can get different artifacted colors, so it might be interesting to combine GRAPHICS 8 with GRAPHICS 15 using a custom display list, and use flicker/dither with the GRAPHICS 8 lines to get some colors that aren't quite the same as if you were using GRAPHICS 15. Michael Rideout
-
Okay, I used the wrong term, I guess an easy way to remember it is "factor" = multiply. The term I should have used is "triangular number." The number of different combinations of 128 colors is as I said, 129 * 64 = 8256. This assumes that two combinations are considered to be equal if they involve the same colors (e.g., color 30 mixed with color 46 is the same as color 46 mixed with color 30). For example, the SECAM 2600 has only 8 colors, so the combinations are color 0 mixed with color 0, 1, 2, 3, 4, 5, 6, or 7 (8 mixtures), color 1 mixed with color 1, 2, 3, 4, 5, 6, or 7 (7 mixtures), color 2 mixed with color 2, 3, 4, 5, 6, or 7 (6 mixtures), color 3 mixed with color 3, 4, 5, 6, or 7 (5 mixtures), color 4 mixed with color 4, 5, 6, or 7 (4 mixtures), color 5 mixed with color 5, 6, or 7 (3 mixtures), color 6 mixed with color 6 or 7 (2 mixtures), color 7 mixed with color 7 (1 mixture), = 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 = (8 + 1) + (7 + 2) + (6 + 3) + (5 + 4) = 9 * 4 = 36 mixtures The general formula is (X + 1) * X / 2, as Thomas said. *However*, in actual practice the number of *discernible* mixtures produced can be considerably less than that, depending on the colors being mixed, and the method being used to mix them. For example, the GIF image I posted for the 8 SECAM colors (created in a paint program rather than on a real Atari) shows 36 mixtures, but some of them look very similar to each other. Using RGB color space to illustrate, mixing red [1,0,0] with green [0,1,0] produces dark yellow [.5,.5,0]-- the sum of the RGB values divided by the number of colors being mixed. Thus, mixing red [1,0,0] with cyan [0,1,1], or green [0,1,0] with magenta [1,0,1], or blue [0,0,1] with yellow [1,1,0] produces the same color-- gray [.5,.5,.5]. This assumes that the colors are being mixed as completely as possible, or as a single pixel. With flickering, or with alternating colors via interlacing, the original colors are still somewhat visible, so the mixtures may appear slightly different. Applying this to the NTSC Atari's 128 colors, we can say that the mixture of two colors is the sum of the hues, divided by 2, and the sum of the luminances, also divided by 2. This isn't quite right as far as the hues are concerned, because it matters which hues we're talking about (e.g., hue 1 mixed with hue 15 is *not* hue . Nevertheless, in theory, color 0 (hue 0, luminance 0) & color 14 (hue 0, luminance 14) = color 2 & color 12 = color 4 & color 10 = color 6 & color 8 = "color 7" The amount of flickering will be different, but if we could mix those colors exactly (and if the luminances follow regular steps), then the results would be the same. Adding in the hues, we get similar results. For example, color 20 (hue 1, luminance 4) & color 38 (hue 2, luminance 6) = color 22 (hue 1, luminance 6) & color 36 (hue 2, luminance 4) = hue "1.5", luminance "5" Keeping in mind that the flickering is least when the hues and luminances are closest together, the best (least flickery) results are obtained by mixing adjacent hues and adjacent luminances. So for any given hue, we can get 15 luminances-- the 8 luminances which the Atari can produce for that hue, plus the 7 luminances which are halfway between them (i.e., luminances 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, and 14). And we can get something like 46 hues-- the 16 pure hues, plus 15 hues between the 15 pure colorful hues (i.e., hue 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, and 15.5-- where "15.5" is hue 15 mixed with hue 1), plus another 15 hues which are the 15 pure hues mixed with hue 0. Putting these together, we get something like 690 colors (15 luminances of 46 hues). Obviously, these aren't the *only* possible combinations. And if we can mix the colors using dithering along with flickering (as I've successfully done in the past on the XL/XE computers), we can get some pretty good mixtures using hues that are nonadjacent. For example, mixing blue with brown can produce dark green if we pick the right shades of blue and brown (think of brown as "dark yellow"). So it's pretty difficult to calculate the exact number of *practical* combinations that can be produced, but it's safe to say that it will be considerably less than X*(X+1)/2. Unfortunately, all of this tends to work better on a TV than on a monitor, and it tends to work better with TVs that have lower resolution than with TVs that have higher resolutions-- at least, that's been my experience. This is due to the "color bleeding" that tends to occur when the TV has a lower resolution, especially when you dither two colors together using the smallest pixels that the Atari can produce. Michael Rideout
-
I haven't been able to try interlacing on a real Atari, but I reviewed the Stella-list posts about interlacing several months ago, and when it was first demonstrated by others it was shown that RSYNC wasn't needed (IIRC). I don't know about modern TVs or computer monitors, but the only thing that was needed a few years back, when it was first demonstrated in Stella-list, was to turn on VSYNC at the correct time, depending on whether the even or odd field was being drawn. By the way, many years ago I was obsessed with getting more colors on my 8-bit Atari (600XL, 800XL, 65XE, and 130XE). I successfully mixed colors very well by combining flickering with dithering, which is easy on an 8-bit but very difficult on a 2600 (because of the difference in resolutions, plus the difference in the graphics features). Anyway, I found that colors could be mixed fairly well by using flickering with alternating scan line colors, rather than using dithering, but the results weren't quite the same. For example, a RYRYRYRY checkerboard pattern flickered with a YRYRYRYR checkerboard pattern creates a pretty good solid orange (but it tingles if you move your eyes), whereas alternating RYRY lines flickered with YRYR lines also produces orange, but it looks slightly different. This is due to the bleeding of colors that results when colors are put side-by-side on a line, such that using a dithered checkerboard design mixes the colors a little bit more because the colors bleed together on the TV screen. Without dithering, there is no color bleeding (if that's the right term to describe it), so the flickering still blends the colors, but they don't look the same. Dithering isn't really feasible on the 2600, unfortunately. Michael Rideout
-
By the way, if you mix X colors, you don't get X-squared combinations, since some of them will be the same (e.g., yellow-red and red-yellow produce the same mix). You actually get X! colors (if I have the notation correct)-- that is, "X factorial" (if I'm using the correct term). For example, mixing 8 colors gives you 8+7+6+5+4+3+2+1, or 36 different mixes. So mixing 128 colors gives you 128+127+126+...+3+2+1, or 64*129 = 8256 different mixes. Michael Rideout
-
When you mix colors by flickering, the results are better (i.e., less obvious flicker) if the colors being mixed are close together in hue or luminance. For example, you could mix hue 2 (yellowish-orange) and hue 3 (reddish-orange) to get more of an "orange-orange," or you can get 15 shades of a particular hue by mixing two consecutive luminances (i.e., luminance 0 and 2, or 2 and 4, or 4 and 6, or 6 and 8, or 8 and 10, or 10 and 12, or 12 and 14). Creating an interlaced display can be either good or bad for mixing colors. On the plus side, the combined scan lines will be closer together. But on the minus side, the colors that you're trying to mix won't be drawn directly on top of each other, so they won't mix together as well. By the way, as I understand it, there's no need to use RSYNC when creating an interlaced display. All you need to do is draw 262 complete lines (on an NTSC 2600), then start drawing a 263rd line, but turn on VSYNC halfway through the line. Obviously, this means you'll need to count machine cycles or color clocks so you'll know when to turn on VSYNC. The next field should automatically begin with half of a scan line, so you'll need to keep that in mind when you're counting the scan lines (i.e., the first line is not a full line, so don't start counting until *after* the half line). Then, at the end of the second field, turn on VSYNC as soon as the last line has been drawn. Last year I started to write a game called "Quest for the Lost Pyramids of Atlantis," which I've put aside for the time being, but my plan was/is to have NTSC, PAL, and SECAM versions combined in one game, controlled by the difficulty switches. And I was using interlacing to get more colors in the SECAM version. After I made a few test screens, I started working on the title screens, which implement the interlacing, etc. I'm attaching my last working copy of the title screens, which can be displayed in NTSC, PAL, or SECAM. All three versions use an interlaced screen, but only the SECAM version uses the interlacing to mix colors. To run it on the z26 emulator, use Z26.EXE -g7 -v3 -! LSTPYR1H.bin for SECAM, use Z26.EXE -g7 -v3 -1 -! LSTPYR1H.bin for PAL, and use Z26.EXE -g7 -v3 -0 -! LSTPYR1H.bin for NTSC. If you run it for the SECAM version, you may need to use the "-" key to switch from the PAL palette to the SECAM palette (which should show yellow letters on a red screen, with red and black mixed together on the bottom part). If you can load it into a Cuttle Cart or Krokodile Kart on a real Atari, set the left player difficulty to "hard" for NTSC. Set the left difficulty to "easy" for PAL or SECAM. The right difficulty chooses between PAL and SECAM-- "easy" is SECAM, and "hard" is PAL. At least, I think that's correct! I can't test it on a real Atari, just an emulator, so I have no idea how well it works on a real Atari, if at all! And the title screens are kind of boring, but if anyone can test it on a real SECAM 2600, at least they can tell us how well the interlaced color-mixing works (if at all). Michael Rideout PS-- I'm also attaching a picture I made in a graphics program to try to see how interlaced colors might look on a SECAM 2600. It simulates interlacing by using alternating colors. I should be able to create an actual binary that would show the same sort of display on a real Atari, if anyone with a SECAM 2600 is interested. LSTPYR1H.BIN
-
Thanks, Rybags, this is very cool, and it rings a bell from my computer science classes back in college. Michael Rideout
-
Just a thought, maybe you could pass your assembly routine the column and row number you want to print to, and have it calculate the screen position from there? Or, you could also add the length, if you are printing long strings to the screen. Not sure what/how/why you're doing this, so don't know what suggestions would make sense/fit in with your needs. Michael Rideout
-
Yes, that's correct, as long as the players are positioned appropriately, such as Player 0 horizontal position = 48 Player 1 horizontal position = 80 Player 2 horizontal position = 112 Player 3 horizontal position = 144 Player 4 horizontal position = 176 * * When using this technique, it's convenient to combine the four missiles into a fifth player. Michael Rideout 956913[/snapback] Actually, it makes more sense to position player 4 first, followed by the other players. That way you have your players set up in the order they appear in memory space. Using the 5th player has some advantages, but it depends on what your color needs are because it uses a color register already used in antic 4 (COLOR3 to specific). I find that once the initial positions are set for the four missiles, it's easy to write to them as a unit because they share memory space, as if they are one player already. 956993[/snapback] I was disassembling my routine that uses P/M underlays in GRAPHICS 0, and I see that that's exactly the way I had done it. And I didn't actually combine the missiles into another player (color-wise), since I was setting all four players to the same color anyway, but they were positioned so as to create another player in effect: 48 for M3 56 for M2 64 for M1 72 for M0 80 for P3 112 for P2 144 for P1 176 for P0 It's murder trying to disassemble my routine to debug it, because I can't find my original notes, but I think my problem may be emulator-related. If I remember correctly, it was working great with one emulator, then I installed a different one and the program stopped working. It might be the way certain things are set, as I've discovered that some of my programs won't work correctly unless I have a particular setting enabled (mainly the "ROM patch" setting). Also, about the same time that I was downloading different emulators, I was also downloading different OS ROMs, so there might be a problem there. Once I get my routine disassembled and commented, and get it working with the emulators again, I'll post the disassembly. By the way, can anyone recommend a good disassembler? I'm using dis6502 1.9, but it doesn't seem to have all the features (menus and options) that are shown in the documentation for an earlier version. Part of my problem was getting the file into a format that would disassemble, since it's a raw binary file without headers, so I had to hack it to add the headers so it would even load into the disassembler. And the "dump" window doesn't show anything, so I can't tell the disassembler which bytes are data, and it tries to disassemble them. I've saved the listing and am now editing it in an IDE, but it would be nice if dis6502 would load raw binaries that have no headers, and let me edit the disassembly listing. Michael Rideout
