-
Content Count
5,587 -
Joined
-
Last visited
-
Days Won
2
Content Type
Profiles
Member Map
Forums
Blogs
Gallery
Calendar
Store
Everything posted by SeaGtGruff
-
Copying and pasting the results would be fine with me. I just hope we'll be able to do the reverse. Paste some sprite code into the sprite editor and it will read it, flip it, and display it so you can edit it. If we could have a smarter playfield editor, that would also be great. Maybe the user could select between the two types of results. One option would use data statements and the other would use pfpixel, pfhline, and pfvline. The user could determine which one is best for each task. 989028[/snapback] I played around with Crimson Editor last night, and it works great-- very easy to use, and easy to add user-defined tools to the menu. I had the terminology wrong. The user-defined macros are for recording and replaying a series of keystrokes-- which is also useful; e.g., you could create a macro for something like "if joy0fire then", and you could use the macro to type that out for you everytime you needed to check the fire button in your program. It's easy to customize Crimson Editor as far as adding new languages or changing the user preferences. I set up batari BASIC for the ".bB" extension, since ".bas" is already defined for Visual Basic, but the users can easily change the extension to something else, like ".26b", or even redefine the ".bas" extension to be used for batari BASIC if they won't ever use Crimson Editor for Visual Basic programming. I added "batari BASIC Files" to the file types, and defined the known extensions for it as "*.bB;*.26b;*.bas", so if you're browsing a directory for bB files, any programs with those three extensions will show up in the files listing-- but again, the user can change that if desired. In fact, you don't need to define a language at all, you can just write bB programs without setting anything up. The main advantage of defining a new language is that it allows Crimson Editor to highlight all the keywords for that language in different colors, plus the ability to display just the files of that language type in a file listing. I set up two user-defined tools-- "Compile bB Program" (it just calls the compile batch and shows the results of the compile in an output window), and "Run bB Program in z26" (it just invokes z26 with the name of the compiled program). The user can change that to use Stella or some other emulator instead. And it's easy to modify the command to use any switches desired, so there could be multiple tools for running a program-- e.g., one to run a standard 2k or 4k ROM, another to run a 16k ROM that uses M-Network bankswitching, another to run ROMs that use Atari bankswitching, etc. Since the text output from a program can be captured and displayed in the output window, if someone were to write a program for creating or editing playfields, and output the necessary statements (data, pfpixel, pfhline, or pfvline), then the output could be shown in Crimson Editor's output window, and could be cut and pasted into the bB program. I'm not up to writing a tool like that right now, but if no one else can do it, then I might be able to write something in Visual Basic for playfield editing, player editing, or even color selection (i.e., click on a color in the palette display, and it returns the appropriate hexadecimal or decimal value to the output window). However, my first priority is to work on the tutorial and finally launch it, so I won't be attempting to write any tools like that until sometime in the future. Michael Rideout
-
I hadn't thought about that! The only potentially negative thing I'd seen so far about Crimson Editor is that it doesn't seem to have hex viewer/editor capabilities, which can be useful for viewing and hacking non-disassembled binary files, but which shouldn't be very much needed for actual bB and 6502 programming. Crimson Editor is a general-purpose IDE (not specific to any target computer or game console or programming language), so it doesn't have built-in tools for creating and editing player and playfield graphics for the Atari 2600. It should be possible to create such editors as separate programs and call them with macros, but the resulting code would have to be cut-and-pasted into the bB program. That's what's nice about an IDE like 2600IDE-- since it's tailor-made for a given language and machine, it can include only those menu functions which are needed, and can contain built-in tools that are fully-integrated into the IDE. On the other hand, a general-purpose IDE can have so many menu functions that the user is apt to be bewildered and intimidated, plus there are no built-in tools for doing specific things (like playfield editing) that are specific to a given machine. To be honest, I don't especially like the playfield editor that's in 2600IDE-- not because of the way it works, but because of the code it generates. It creates a series of pfpixel statements, and drawing a playfield by turning the individual pixels on or off with a series of pfpixel statements takes a lot of machine cycles and ROM. It would be better if the playfield editor created data statements for the playfield, similar to the way I drew the castle in the sample program I posted in another thread-- although that would also require the user to call a routine for moving the resulting data into the playfield's RAM locations, flipping the bytes that need to be flipped, as in my sample program. Depending on the screen (i.e., how many pixels are to be turned on, and how they're positioned relative to each other), moving 48 bytes into playfield RAM can be a much quicker way to draw the playfield, and might require less ROM as well. But for some playfields, it might be quicker to use pfpixel, pfhline, and pfvline to draw the screen-- assuming that the playfield is already cleared. If the playfield needs to be cleared each time anyway, then the bytes approach is probably better anyway as far as speed, but might take up more ROM than using just a few pfpixel, pfhline, and pfvline statements. I guess I could include information on both-- 2600IDE and Crimson Editor. But it would be simpler to cover just one editor in the tutorial, since I'd like to include screenshots where appropriate. I'll play around with Crimson Editor this weekend to see how well it works-- after all, I might want to use it myself whether or not it's the IDE that I end up covering in my tutorial. Actually, I prefer to use Multi-Edit, since it's what we use at work (so I'm very familiar with it), and I bought a copy for myself earlier this year. But Multi-Edit is probably way too expensive for most of the people who'll be reading my tutorial, whereas Crimson Editor is free. Michael Rideout
-
I have the week off between Christmas and New Year's, so I plan to work on my bB tutorial and finally launch it. Since it's aimed at beginners, I'm including some instructions on how to use an IDE. I'd originally planned to use 2600IDE, but now I'm thinking about using a free full-featured IDE. After doing a brief search, I just downloaded Crimson Editor. I'm sure there are many other free IDEs to choose from, but this was one of the first ones I saw that looks fairly robust. Of course, now I have to build some custom files so Crimson Editor will recognize and be able to highlight the bB keywords, 6502 opcodes, and 2600 register names, as well as macros for compiling and running bB programs. This brings me to two questions before I invest much time in setting up the custom files for Crimson Editor: (1) Does Crimson Editor meet with most everyone's approval? What I mean is, do any of you who are already programming in bB, or who are thinking of starting to program in bB, have any other free IDEs that you want to suggest I use instead of Crimson Editor? The main features I'm looking for are (a) color highlighting of the keywords and the ability to customize the keyword list for a new language; (b) full editing features, e.g., search and replace; © automatic backups and the ability to configure the backup feature; and (d) the ability to create macros for compiling programs and running programs. Anyone with strong feelings in favor of another IDE, or against Crimson Editor, should please speak up now. I just downloaded it and haven't really tested it yet (I can't very well try it out with bB until I customize it for bB, which I haven't done yet), so if anyone having familiarity with Crimson Editor knows of any glaring glitches or annoying shortcomings, please let me know. (2) The file extensions I've been using with bB and 2600IDE-- .bas and .asm-- are already used for other languages. Of course, I could just trash the syntax files for those extensions, but it might be a good idea for us to come up with file extensions that are more unique to bB and 6502 assembly. I know that 2600IDE uses .26b as one of the recognized file extensions for bB source files, so I could set up custom files under that extension, or I could use something else, like .2600bas, .bB, etc. And .asm is a popular file extension among 6502 assembly programmers, but it's also used with other assembly languages, so we could come up with an extension for 6502 assembly source files in general, or even for Atari 2600 assembly source files in particular-- like .26a, .2600asm, etc. Does anyone want to offer comments or suggestions about this issue? Of course, people could create their own custom syntax files and macros, etc., but I'd like to set things up in advance as much as possible for the readers. Thank you, Michael Rideout
-
To create small playfield pixels, you can write a custom kernel, but it depends on where you want to store the data-- RAM or ROM. The neat thing about the existing bB kernel is that the playfield data is stored in RAM, so it makes it easier for a beginner to create a simple playfield display-- and that's adequate enough for games like Adventure and Superman, which used big blocks (many scan lines tall) for the playfield (castles, city skylines, mazes, etc.). If you want to get the data from a ROM table yourself as you're drawing the playfield, you can create a simple custom kernel in your program. Ditto with multicolor sprites, you can store the shape and color data for each scan line (or pair of scan lines, whatever your vertical resolution is going to be) and move the data into the registers yourself in the kernel. If you use the M-Network bankswitching ability that I made custom includes for a while back, you can store the data in the expanded RAM areas. I didn't mean to sound bitchy or whatever, and my original lengthy post was not so much a rant (well, OK, it was sort of a rant) as an urging for everyone to get creative and try to do things with bB as it is, much the same way you would with assembly-- which, after all, doesn't have multicolor sprite commands and such, you have to write the code yourself. First off, bB's original documentation states that it's intended in part to be a stepping-stone to learning assembly programming. And as I see it, the most spectacular thing about bB isn't how easy it makes it to do certain things (like put a player on the screen), but rather its sheer flexibility and ability to be customized via user-written include files. My point is that we really aren't limited to bB's builtin commands or canned kernel, we can use it as a tool for writing fancy stuff of our own. That is, just because bB has a canned kernel doesn't mean we can't write kernels of our own. Also, creative ideas are fine for coming up with cool solutions, but a big part of programming success (for me, at least, because I'm not a great programmer) is to be too stupid to know your own limits (so you aren't afraid to try something that everybody smarter than you insists is impossible), and to be too stubborn to know when to quit (so you keep trying until you either succeed, or accomplish something different from what you intended, but that's pretty cool in its own right)! I know that bB is a wonderful programming platform in its own right, but a big part of what makes it so incredibly powerful is not any of the canned stuff that it gives us to work with, but rather the ability to build nifty tools (routines) of our own. The only way we'll ever be able to unlock the full potential of bB is to write our own kernels or routines with it, otherwise we're stuck with whatever canned kernels or routines batari is able to add to it. Not that I mind batari's efforts to add new canned features and stuff-- I think he's doing a super spectacular job, and bB is pretty awesome even as it is now. By the way, a while back I was trying to compare bB with BASIC (for my tutorial which I want to do), and my point was that bB isn't really BASIC, because it has only a few of BASIC's commands, it has many of its own commands that aren't in BASIC, some of its operators (logical operators) are more like C than BASIC, etc. (my real point being that since bB isn't BASIC, we can't expect to be able to type in a BASIC program listing and compile it with bB). But the other night I was searching for information on the original BASIC, and I discovered that BASIC originally had only 15 commands-- almost all of which are already available in bB (although a couple of them behave very differently)! So I guess bB really is a dialect of BASIC! BASIC's original 15 commands, and whether or not bB has them: LET yes READ no DATA yes (but behaves differently) PRINT no (not yet, but maybe soon) GOTO yes IF-THEN yes FOR yes NEXT yes END yes (but behaves differently) STOP no DEF no GOSUB yes RETURN yes DIM yes (but behaves differently) REM yes Michael Rideout
-
Well crap, I had a long bitchy post written about how we should all start writing our own bB custom kernels and other tricks instead of whining to batari to add stuff for us, and I lost my connection and the post got wiped out! I guess it's just as well. Anyway, I was basically trying to point out that a lot of really cool things can be done in bB right now, without any new commands or features having to be added by batari. For example, we can create custom kernels using only bB code (here's an example, the Atari rainbow); or defining the playfield with binary data sort of the way it's done in Adventure; or putting player data in a strip of ROM data and displaying the desired shape by pointing bB to it; or even creating modifiable player shapes by putting the player data in RAM! For the player example, push up to see a circle, push left to see a square, and push right to see a triangle. For the RAM player example, move the snake around. The positioning is buggy, the snake doesn't turn correctly, but it should work well enough to give an idea of what I was trying to accomplish. Michael Rideout playfield_example.bas playfield_example.bas.bin player_example.bas player_example.bas.bin ram_player_example.bas ram_player_example.bas.bin reverse_rainbow_2.bas reverse_rainbow_2.bas.bin
-
Could you provide both solutions using alternate kernels? Then the programmer could select which include file to use to get the kernel he or she wanted. Also, is the original kernel going to be retained as an alternate, so that any existing bB programs won't be broken by the new version? I know most everyone is eager to get the multi-sprite capability, but it seems to me that most games tend to have rather specific kernels anyway, as dictated by the needs of the game. I'd rather see a collection of different canned kernels which could be selected from. In fact, it might be nice to have a SET comand for specifying which kernel to compile into the game, like "set kernel=original" or "set kernel=multisprite". Michael Rideout
-
The DASM program is used to assemble (compile) an assembly code file into a binary ROM image file. What you want to do is the reverse of that, take a binary ROM image file and disassemble it into an assembly code file. DASM can't do that, but a 6502 disassembler can. And to disassemble Atari 2600 ROM images, the best program to use is Distella. Go to http://www.atariage.com/2600/programming/index.html and scroll down until you see the link for Distella, and click on it. Oops, sorry, I just tried that and the link isn't working! Go to http://members.cox.net/rcolbert/distella.htm instead, and download version 3.0 for the latest and greatest. Michael Rideout
-
OK, so my old desktop computer died, my boss gave me one of his old ones that he wasn't using any more, and this weekend I'm getting it set up, like installing bB on it, emulators, etc. So I created a folder called C:\Atari, and under it I created folders called 2600, 5200, 7800, and 800, like on my old computer. I downloaded and installed the various versions on bB in a folder called C:\bB, but then decided it would be better to move the bB folder inside the \Atari\2600 folder. But as I was about to do that, I had this crazy thought... bB is basically a high-level language to help create 6502 assembly source files that are then assembled into binary ROM images with DASM. Right now, bB is aimed at the 2600-- the header files, include files, and commands are specifically tailored for the 2600. But aside from the way the zero-page variables are defined, and the way the commands are currently tailored for the 2600 in particular, bB doesn't really know or care what machine the program is being written for. So wouldn't it be possible to create alternate header files, include files, and commands tailored for the other Atari machines? For example, maybe we could have a bB "machine" command, or "set machine=xxx" command, that would go at the beginning of a bB program, to specify which machine the program is being written for? Then, based on whatever that command is set to, the bB compiler could compile the source code using whichever header/footer/other include files are needed. After all, most of bB's commands (except the ones that are changed to assembly code by the bB compiler) are contained in routines located in the include files, so therefore any machine-specific routines (like drawing the playfield, the display kernel, etc.) could have their own separate include files. The resulting 6502 source code would then be assembled with DASM, and the final binary file could be run on the appropriate machine. In other words, we could use bB to write games for the 2600, or 7800, or 5200, or 800 et al. Now, admittedly this would take a lot of work to accomplish, there are already very powerful languages available for the 800 et al, and I think we should worry about further developments and improvements of bB for the 2600 before thinking about adding any support for other machines. And I'd personally prefer seeing support for the 7800 added before any support for the 5200 and 800 et al (simply because there's currently nothing for the 7800, and quite a few languages for the 800 et al-- with the 5200 essentially being like the 800 et al, so I presume that games for the 5200 can be developed using languages for the 800 et al?). But it strikes me that it would be very cool if some day (probably at least no sooner than a few years from now) we could use bB to create games for the 7800, 800, etc., in addition to games for the 2600! (I told you it was a crazy thought!) Michael Rideout
-
Would this be Possible ?, some thoughts
SeaGtGruff replied to Retro Archaeologist's topic in batari Basic
Unless you use interlacing (very rare on the 2600), a scan line is the smallest unit of vertical resolution. Many Atari 2600 games draw the same thing on pairs of consecutive scan lines, though it's often possible to move things vertically in one-line increments. 983637[/snapback] okay so like one PC style pixle tall than, i know the scanline is a group of pixels crammed together in a line from left to right, so i thought i might be 1 pixel tall from top to bottom. in any case thats answers that . RA 983645[/snapback] You asked the question backwards, it ought to be "A pixel is how many scan lines tall?" And the answer is that a pixel can be any number of scan lines tall, since the graphics features extend from the top of the screen to the bottom of the screen in the sense that once you set them on or off, they stay that way until you change them. So for example, if you set a particular playfield pixel on, it will create a line that extends from the top of the screen to the bottom of the screen, until you set that same playfield pixel off, hence you can make the playfield pixels be 1 scan line tall, or 2, or 3, or 4, etc., up to the height of the screen. At the same time, the player pixels can be left as is or changed, so they can also be any height. And the same holds true of the ball and the missiles. (I'm not referring to bB, which uses a canned kernel that updates the players every 2 scan lines, and updates the playfield every 16 scan lines-- with the exception of PF0 pixels, which stay on or off for the full height of the screen.) Or, to put it in terms of the way you asked the question, a scan line can be 1 pixel tall, or 1/2 pixel tall, or 1/3 pixel tall, or 1/4 pixel tall, etc., if you see what I mean. Michael Rideout -
Just to keep everyone updated on my bB tutorial-- I've been working on it, and had considered holding off until the next version of bB is released (since it sounds like it's going to be a major upgrade), but my computer died, so I can't access any of my work right now. The hard drive is OK, the power unit died, and I should be able to recover all of my work by either swapping my hard drive into another old computer (I know someone with an old one to sell), or fix it up to work as an extra external hard drive once I get my new computer. Right now I'm using "my" office laptop, and I've been needing a good excuse to buy a new computer anyway, so I guess I don't mind that my old 1998 clunker of a desktop finally bit the dust! Michael Rideout
-
Would this be Possible ?, some thoughts
SeaGtGruff replied to Retro Archaeologist's topic in batari Basic
The games using no bankswitching will compile almost exactly as they did before. The only difference is that the graphics data are placed immediately after the bB code instead of being mixed in. This had to be done anyway because the multisprite kernel needs graphics to be placed stategically, but it also made bankswitching much easier. 983590[/snapback] That sounds great! I was worried about how it might affect the customization I'd done for M-Network bankswitching, which I think works best if all of bB's code (included routines, as opposed to the programmer's code) can be compiled to occupy the fixed ROM area so it's available to all banks. Michael Rideout -
Would this be Possible ?, some thoughts
SeaGtGruff replied to Retro Archaeologist's topic in batari Basic
bB already has this, at least sort of. LET (i.e., "=") is the equivalent of POKE, since it works with 1-byte variables, although the only thing you can "poke" into are the variables in RAM or the TIA registers (which don't keep their values). And IF or LET will sort of let you do a PEEK, in the sense that you can use IF to do something if a byte has a certain value, or you can LET a variable equal the value of any memory location. You can also use DIM to help you define the memory locations you're interested in. So for example, suppose you want to do something like "POKE 198, 7"-- you just say "variable = 7," where "variable" is a RAM variable that resides at location 198. Or "POKE COLUBK, 68" would just be "COLUBK = 68," since COLUBK is the name of a TIA register. You can't "poke" anything into ROM locations, but you can "poke" into registers or into RAM, including any extra RAM that's added by a particular bankswitching scheme (a few of which do add extra RAM). If you want to do something like "A = PEEK(65500)," you just start out saying something like "dim location=65500" near the beginning of your program (or it can actually go anywhere, even at the end), and then "a = location," which sets the variable a (or A, they are equivalent) to the value in address 65500. So, there's really no need for PEEK and POKE, they are pretty much necessary only in a BASIC that doesn't have 1-byte variables, whereas bB uses 1-byte variables by default. Michael Rideout -
Would this be Possible ?, some thoughts
SeaGtGruff replied to Retro Archaeologist's topic in batari Basic
No need to worry about that in a few weeks - I've modified bB to create 8k, 16k, or even 32k binaries now. I think I've come up with a reasonable way to handle bankswitching, so most of it is transparent to the programmer. Still working on optimizations. But it will ne included in the next release regardless. 983386[/snapback] Out of curiosity, will the games that *don't* use the 8K, 16K, or 32K bankswitching (which I assume will be with Atari's method) still compile with everything in one place, or will they be split up into two areas as you'd mentioned doing to get the Atari bankswitching to work? Michael Rideout -
You can't do it with the existing "canned" kernel, unless you use flickering-- e.g., to draw two independent player0 shapes, draw the first player0 shape on the odd frames, and draw the second player0 shape on the even frames. The ability to do that without flickering (well, except where the two shapes overlap on scan lines) is hoped for in the next version of bB, which may be released in January. However, I'm not sure how that's going to affect the RAM variables. Right now, 5 bytes are needed just for 1 copy of player0 (player0x = 1 byte, player0y = 1 byte, player0pointer = 2 bytes, and player0height = 1 byte), so for, say, 6 independent copies of player0, 30 bytes will be needed. That's 25 bytes more than currently, which means the 26 user variables (A through Z) would be toast-- and that's not even allowing for multiple copies of player1! Of course, you don't need to use the "canned" kernel. If you have very specific wants and needs (e.g., you won't be using the ball or missiles, just player0 and player1, and you aren't going to need an asymmetrical playfield), and if timing isn't a super-critical issue on each scan line, then you might be able to write your own game-specific kernel using all bB commands (i.e., for...next, if...then...else, goto, gosub, let). And if timing is an issue, you can always write your own kernel using inline assembly code. For example, the attached program is an all-bB custom kernel that I wrote last night to display the 2600's 128-color palette using only the background. Clearly, that kernel won't do you any good for multi-player graphics, but at least it shows that you can write all-bB custom kernels instead of calling drawscreen. Michael Rideout rem * A simple NTSC display kernel written in bB. rem * "The Atari's 128-Color Palette" (:^p~ rem ============================================= rem * Initialize the 2600's audio and video. rem * (bB actually clears the 2600's registers for us, rem * but you need to do this sort of thing if you're rem * writing pure assembly programs outside of bB.) PF0 = 0 : rem * Turn off playfield 0. PF1 = 0 : rem * Turn off playfield 1. PF2 = 0 : rem * Turn off playfield 2. GRP0 = 0 : rem * Turn off graphics for player 0. GRP1 = 0 : rem * Turn off graphics for player 1. ENAM0 = 0 : rem * Turn off enable for missile 0. ENAM1 = 0 : rem * Turn off enable for missile 1. ENABL = 0 : rem * Turn off enable for ball. AUDV0 = 0 : rem * Turn off audio volume for sound 0. AUDV1 = 0 : rem * Turn off audio volume for sound 1. loop rem * Draw 30 blanked scan lines. VBLANK = 2 : rem * Turn on video blanking. for x = 1 to 30 : rem * Do next part 30 times. WSYNC = 0 : rem * Wait for next horizontal sync. next rem * Send vertical sync signal for 3 scan lines. VSYNC = 2 : rem * Turn on vertical sync. for x = 1 to 3 : rem * Do next part 3 times. WSYNC = 0 : rem * Wait for next horizontal sync. next VSYNC = 0 : rem * Turn off vertical sync. rem * Draw 36 more blanked scan lines. for x = 1 to 36 : rem * Do next part 36 times. WSYNC = 0 : rem * Wait for next horizontal sync. next rem * Turn video back on. VBLANK = 0 : rem * Turn off video blanking. rem * Draw hue 0 and its luminances for 11 scan lines. x = 0 hue_0_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_1 COLUBK = $00 COLUBK = $00 COLUBK = $02 COLUBK = $04 COLUBK = $06 COLUBK = $08 COLUBK = $0A COLUBK = $0C COLUBK = $0E COLUBK = $00 goto hue_0_loop rem * Draw hue 1 and its luminances for 11 scan lines. hue_1 x = 0 hue_1_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_2 COLUBK = $00 COLUBK = $10 COLUBK = $12 COLUBK = $14 COLUBK = $16 COLUBK = $18 COLUBK = $1A COLUBK = $1C COLUBK = $1E COLUBK = $00 goto hue_1_loop rem * Draw hue 2 and its luminances for 11 scan lines. hue_2 x = 0 hue_2_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_3 COLUBK = $00 COLUBK = $20 COLUBK = $22 COLUBK = $24 COLUBK = $26 COLUBK = $28 COLUBK = $2A COLUBK = $2C COLUBK = $2E COLUBK = $00 goto hue_2_loop rem * Draw hue 3 and its luminances for 11 scan lines. hue_3 x = 0 hue_3_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_4 COLUBK = $00 COLUBK = $30 COLUBK = $32 COLUBK = $34 COLUBK = $36 COLUBK = $38 COLUBK = $3A COLUBK = $3C COLUBK = $3E COLUBK = $00 goto hue_3_loop rem * Draw hue 4 and its luminances for 11 scan lines. hue_4 x = 0 hue_4_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_5 COLUBK = $00 COLUBK = $40 COLUBK = $42 COLUBK = $44 COLUBK = $46 COLUBK = $48 COLUBK = $4A COLUBK = $4C COLUBK = $4E COLUBK = $00 goto hue_4_loop rem * Draw hue 5 and its luminances for 11 scan lines. hue_5 x = 0 hue_5_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_6 COLUBK = $00 COLUBK = $50 COLUBK = $52 COLUBK = $54 COLUBK = $56 COLUBK = $58 COLUBK = $5A COLUBK = $5C COLUBK = $5E COLUBK = $00 goto hue_5_loop rem * Draw hue 6 and its luminances for 11 scan lines. hue_6 x = 0 hue_6_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_7 COLUBK = $00 COLUBK = $60 COLUBK = $62 COLUBK = $64 COLUBK = $66 COLUBK = $68 COLUBK = $6A COLUBK = $6C COLUBK = $6E COLUBK = $00 goto hue_6_loop rem * Draw hue 7 and its luminances for 11 scan lines. hue_7 x = 0 hue_7_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_8 COLUBK = $00 COLUBK = $70 COLUBK = $72 COLUBK = $74 COLUBK = $76 COLUBK = $78 COLUBK = $7A COLUBK = $7C COLUBK = $7E COLUBK = $00 goto hue_7_loop rem * Draw hue 8 and its luminances for 11 scan lines. hue_8 x = 0 hue_8_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_9 COLUBK = $00 COLUBK = $80 COLUBK = $82 COLUBK = $84 COLUBK = $86 COLUBK = $88 COLUBK = $8A COLUBK = $8C COLUBK = $8E COLUBK = $00 goto hue_8_loop rem * Draw hue 9 and its luminances for 11 scan lines. hue_9 x = 0 hue_9_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_10 COLUBK = $00 COLUBK = $90 COLUBK = $92 COLUBK = $94 COLUBK = $96 COLUBK = $98 COLUBK = $9A COLUBK = $9C COLUBK = $9E COLUBK = $00 goto hue_9_loop rem * Draw hue 10 and its luminances for 11 scan lines. hue_10 x = 0 hue_10_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_11 COLUBK = $00 COLUBK = $A0 COLUBK = $A2 COLUBK = $A4 COLUBK = $A6 COLUBK = $A8 COLUBK = $AA COLUBK = $AC COLUBK = $AE COLUBK = $00 goto hue_10_loop rem * Draw hue 11 and its luminances for 11 scan lines. hue_11 x = 0 hue_11_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_12 COLUBK = $00 COLUBK = $B0 COLUBK = $B2 COLUBK = $B4 COLUBK = $B6 COLUBK = $B8 COLUBK = $BA COLUBK = $BC COLUBK = $BE COLUBK = $00 goto hue_11_loop rem * Draw hue 12 and its luminances for 11 scan lines. hue_12 x = 0 hue_12_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_13 COLUBK = $00 COLUBK = $C0 COLUBK = $C2 COLUBK = $C4 COLUBK = $C6 COLUBK = $C8 COLUBK = $CA COLUBK = $CC COLUBK = $CE COLUBK = $00 goto hue_12_loop rem * Draw hue 13 and its luminances for 11 scan lines. hue_13 x = 0 hue_13_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_14 COLUBK = $00 COLUBK = $D0 COLUBK = $D2 COLUBK = $D4 COLUBK = $D6 COLUBK = $D8 COLUBK = $DA COLUBK = $DC COLUBK = $DE COLUBK = $00 goto hue_13_loop rem * Draw hue 14 and its luminances for 11 scan lines. hue_14 x = 0 hue_14_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_15 COLUBK = $00 COLUBK = $E0 COLUBK = $E2 COLUBK = $E4 COLUBK = $E6 COLUBK = $E8 COLUBK = $EA COLUBK = $EC COLUBK = $EE COLUBK = $00 goto hue_14_loop rem * Draw hue 15 and its luminances for 11 scan lines. hue_15 x = 0 hue_15_loop WSYNC = 0 : rem * Wait for next horizontal sync. x = x + 1 if x = 12 then goto hue_15_end COLUBK = $00 COLUBK = $F0 COLUBK = $F2 COLUBK = $F4 COLUBK = $F6 COLUBK = $F8 COLUBK = $FA COLUBK = $FC COLUBK = $FE COLUBK = $00 goto hue_15_loop rem * Draw one more scan line. hue_15_end WSYNC = 0 : rem * Wait for next horizontal sync. goto loop palette.zip
-
What you'd need to do, if you want to use pfpixels for both the snake and the maze, is draw the maze first, before you get into the drawscreen loop, and then draw the snake inside the screen-drawing loop. For example, notice how in the following section of code you are gosubbing to draw the logo screen (by which I mean setting the bytes of the playfield equal to the desired values to create the logo text), before you actually get into the drawscreen loop: startme gosub clear : rem <----- this is where you're clearing the screen COLUPF = $44 gosub logo : rem <------ and this is where you're "drawing" the title logo COLUP0 = $00 COLUP1 = $00 : scorecolor = $00 coloring g = g + 1 COLUBK = g : COLUP0 = g : COLUP1 = g : COLUPF = $C4 drawscreen : rem <----- but you don't actually draw the screen until here if joy0fire then goto programstart goto coloring If you clear the screen, draw the maze, draw the last four segments of the snake, and then get into the drawscreen loop, you shouldn't have any problems using the pfpixels for both the maze and the snake. Of course, when you position the snake for the start of the maze on each level, you want to be sure the snake isn't already colliding with a wall. I've been working on an example of drawing a snake with player0, but it's tricky. I started out thinking I would try to define all possible configurations for the player0 data, but that will take up a lot of ROM to define all the variations, plus the ifs for all the variations will require a lot of code. So now I'm working on a routine which defines the player0 data as an 8-byte array in RAM, and calculates what the data should be, based on the direction that each segment of the snake is moving in. As you can imagine, it's tricky, but I've almost got it working the way I want-- except there is a lot of screen flickering, so it appears that the routine is too long. I plan to try splitting it into two or four sections, split across two or four frames, to see if that helps. You can't test for collision between a player pixel and a playfield pixel if the pfpixel is turned off, so you'll need to use a different method of detecting when the snake has moved through the maze exit. One way you could do it is to check the snake's position. For example, if you know the exit is in column 0 of the playfield array, and in rows 4 and 5, then you could check to see if the snake's head is in column 0, row 4 or row 5. Another way you could do it is to leave the playfield alone (i.e., don't open the exit door by turning off any pfpixels), and instead use player1 or missile1 to draw the exit, positioning it on top of the pfpixels where the exit is, and check for a collision between player0 and player1, or between player0 and missile1. You could also use missile0, but if you use player1 or missile1, you can set COLUP1 to the same color as COLUBK, so it looks like the pfpixels for the exit have been erased even though they are still turned on. Of course, in your loop you'll probably be checking for a collision between player0 and player1 (or missile1) for something else, like to see if the snake is eating something or collecting the key, but you could use a flag to determine whether or not the exit has been revealed. If the collision occurs but the flag is off, then the snake is collecting something rather than touching the exit. But when the snake touches the key, then turn on the flag that says the exit is now available, draw the exit with player1 or missile1, and when another collision occurs go to the next level if the flag is on. Michael Rideout
-
The number of contestants sounds about right. I got only 4 words right, and the one I missed was "TALISMAN," so that sounds right, too. The problem (for me) with that word clue was that it was hidden differently than the rest. The other 9 words were hidden within the panel drawings of the comic, like written in the grass or on the side of a building, etc. But "TALISMAN" was contained within a speech balloon, and was simply in big, bold letters like it was being stressed by the person speaking. I didn't find the clue number that pointed to that panel, so I didn't know a word was hidden there. Michael Rideout
-
Thank you, Fox, the article and routines will be very useful! Michael Rideout
-
Actually, there were 10 words to find, 5 of which were the correct ones. Michael Rideout
-
You're welcome! As for changing the title text color in "The Texas Chainsaw Massacre" (or stopping it from flashing), it looks like the code is here: L53FD: STA WSYNC ;3 LDY #$1A ;2 LDX #$01 ;2 STX AUDC0 ;3 DEX ;2 STX COLUBK ;3 STX COLUPF ;3 ; <--- This initializes the playfield color I think LDA $F0 ;3 AND #$7F ;2 CMP #$20 ;2 BCS L541D ;2 LSR ;2 TAX ;2 L5414: AND #$0F ;2 EOR #$0F ;2 ORA #$30 ;2 STA COLUPF ;3 ; <--- This is flashing the playfield color I think DEX ;2 L541D: STX AUDF0 ;3 STX AUDV0 ;3 L5421: STA WSYNC ;3 DEY ;2 L5424: BNE L5421 ;2 LDX #$0E ;2 L5428: LDA #$04 ;2 STA $DF ;3 L542C: LDY #$04 ;2 L542E: STA WSYNC ;3 LDA L5B7E,X;4 STA PF0 ;3 ; <--- Here's where the text is being drawn LDA L5B8D,X;4 STA PF1 ;3 ; <--- These are the left half of the playfield LDA L5B9C,X;4 STA PF2 ;3 ; <--- Still left half of screen LDA L5BAB,X;4 STA PF0 ;3 ; <--- Now begins the right half of the screen NOP ;2 LDA L5BBA,X;4 STA PF1 ;3 ; <--- right half LDA L5BC9,X;4 DEY ;2 NOP ;2 STA PF2 ;3 ; <--- right half BPL L542E ;2 DEX ;2 DEC $DF ;5 BPL L542C ;2 STA WSYNC ;3 INY ;2 STY PF0 ;3 ; <--- Now we clear the playfield STY PF1 ;3 ; <--- after the three lines of title text STY PF2 ;3 ; <--- have been drawn Michael Rideout
-
Sorry, I included the typo in that code. It should be: rem ** move snake's segments for z = 4 to 1 step 255 y = z - 1 snake_col[z] = snake_col[y] snake_row[z] = snake_row[y] : rem ** typo was in this line next snake_col[0] = snake_col[0] + snake_e_w snake_row[0] = snake_row[0] + snake_n_s rem ** is there something there already? z = snake_col[0] : y = snake_row[0] if pfread(z,y) then goto gameover Michael Rideout
-
I couldn't think of a decent way to use a player for the snake, since I figured you'd want the snake to move around and change shape/directions kind of like the way it does in my second example. To do something similar with a player, you'll need to redefine the player shape a whole bunch-- which is doable, but could be very tedious to program because of all the possible shapes. Using a player does offer the advantage that the pixels can be smaller, though. I'll see if I can put together an example that uses a player for the snake, but I can't do it tonight. Well, I expected that you wouldn't want to use wraparound; I just used it in my example because I didn't have any borders/walls, and I was really trying to show how you can program a shape to keep moving in a particular direction until you use the joystick (or cursor control keys in an emulator) to steer it in a different direction. I see a number of problems right away. First, I can't get it to compile as is because you need to include the div_mul.asm file. Add this line at the very beginning of your code: include div_mul.asm (If you got it to compile, then you may have simply omitted that line when you were copying the code into your post.) Next, you have a typo right here: rem ** move snake's segments for z = 4 to 1 step 255 y = z - 1 snake_col[z] = snake_col[y] snake_row[z] = snake_col[y] next In the line that says "snake_row[z] = snake_col[y]", the second "col" should be "row," like this: rem ** move snake's segments for z = 4 to 1 step 255 y = z - 1 snake_col[z] = snake_col[y] snake_row[z] = snake_row[y] next That's the reason it's freaking out, since snake_col can go up to 31, but snake_row should go up to only 10, so setting snake_row[z] equal to snake_col[y] puts the wrong value in snake_row[z], and that value can be much too large. Fix that line, and the snake will move around correctly. Also, I see that you're using b, c, and g in your code, but in the sample code that I'd posted, those variables are being used for other things. It turns out that this is okay, because you aren't using them for different things at the same time. But in general, you should try not to reuse variables like that unless you're sure there won't be any conflicts. In other words, don't use b, c, and g during the actual game play if you're using them for storing other values (e.g., b is used for snake_e_w, c is used for snake_row[0], and g is used for snake_row[4]). This is my fault for not picking other letters to use in my examples, letters that you weren't already using, or that weren't used for other things in my logo screen example. As I said, in this case it's okay, but just be careful when you reuse variables for multiple purposes in the same program. Yes, but it will be trickier and more tedious to do. As I said, I'll try to put together an example, tomorrow night at the earliest. If you're going to use pfpixel to draw both the snake and the walls of the maze, then you'll have to "peek" ahead using the pfread function before you move the snake's head into a new location, like this: rem ** move snake's segments for z = 4 to 1 step 255 y = z - 1 snake_col[z] = snake_col[y] snake_row[z] = snake_col[y] next snake_col[0] = snake_col[0] + snake_e_w snake_row[0] = snake_row[0] + snake_n_s rem ** is there something there already? z = snake_col[0] : y = snake_row[0] if pfread(z,y) then goto gameover Note that this check is being done after the new position of the snake's head has been calculated, but before the snake's head has actually been drawn at the new position, so if the pfpixel at the new position is already on, then it means the snake is about to collide either with itself or with a wall. Yes, I like the flashing colors, too! As for moving from one level to the next, that's up to how you want the game to work, as well as what the goal is. For example, if the primary goal is to navigate the maze without the snake hitting a wall or crossing over itself, then you probably need a secondary goal, too. For example, you mentioned reaching and touching a particular wall or section of wall, which (if you do that) you might want to draw with a player or missile, so it can be a different color than the rest of the maze. Or, you could have an opening in the maze wall, and the snake has to get through the maze and go through the opening to enter the next "room." Or, if you're going to draw both the snake and the maze with pfpixels, then you might use the players and missiles to draw objects that are scattered around the maze, and the snake is supposed to collect (or collide with and "eat") all of the objects without hitting a wall (or itself) in order to "clear" the current maze and advance to the next maze. To go from one level to the next, you could just clear the screen once the current maze has been completed successfully, and draw the next maze, repositioning the snake to the "starting" location for the new level. Also, besides speeding up the game from one level to the next, you might want to keep the same speed for a few levels before speeding up, and have some other kind of difficulty increase, such as starting with a short snake, and adding another segment every level or so to make the snake longer so it's harder to keep it from crossing over itself. Michael Rideout
-
Drawing a playfield the way I demonstrated can definitely help save ROM in many cases, as well as a whole lot of machine cycles. If you're drawing a title screen, the machine cycles might not matter much, if you're setting the playfield pixels just once and then using drawscreen in a loop without setting the playfield pixels over again during each pass through the loop. But if you need to reset/regenerate the screen each time the loop executes, the pf drawing routines can use up a lot of valuable machine cycles, leaving less time for you to do other things. I'm not certain what you mean, but include files don't do any good after a game has been compiled and is running, because you can't "swap out" sections of the ROM by using different include files. It sounds like you really mean bankswitching, not include files. And no, bankswitching isn't unlimited. There are various schemes for implementing bankswitching. A month or two ago I posted a verion of bB 0.35 which allows the use of M-Network's bankswitching method, which can use about 16K of ROM and 2K of extra RAM. You might want to push your game as far as it will go in 4K of ROM to start out with, and then check out bankswitching if 4K isn't big enough to do what you want. Keep in mind that the method I showed you for drawing a playfield requires only 44 bytes per screen (assuming you aren't putting anything in row 11, which is invisible anyway since it's "behind" the score bar), so you ought to be able to squeeze in several screens or mazes by storing them as data that way. I was thinking about this last night after I posted. If the snake has a fixed length, then you can define an array to store the position of each block or segment of the snake, and use a routine to advance each block to the position occupied by the block in front of it, sort of like this: rem * this moves a snake made up of 5 playfield pixels dim snake_n_s = a dim snake_e_w = b dim snake_row = c rem * snake_row is 5 bytes-- c, d, e, f, g dim snake_col = h rem * snake_col is 5 bytes-- h, i, j, k, l dim frame = m dim speed = n snake_n_s = 0 : snake_e_w = 255 : speed = 15 snake_row[0] = 5 : snake_col[0] = 16 snake_row[1] = 5 : snake_col[1] = 17 snake_row[2] = 5 : snake_col[2] = 18 snake_row[3] = 5 : snake_col[3] = 19 snake_row[4] = 5 : snake_col[4] = 20 COLUBK = $00 COLUPF = $C4 rem * plot the snake's position (last 4 segments only) for z = 1 to 4 pfpixel snake_col[z] snake_row[z] on next rem * don't need to draw all 5 segments each frame loop rem * plot the snake's head pfpixel snake_col[0] snake_row[0] on rem * draw the screen frame = 0 wait drawscreen rem * update the snake's direction from the joystick if joy0left then snake_e_w = 255 : snake_n_s = 0 if joy0right then snake_e_w = 1 : snake_n_s = 0 if joy0up then snake_n_s = 255 : snake_e_w = 0 if joy0down then snake_n_s = 1 : snake_e_w = 0 rem * wait a bit to slow things down frame = frame + 1 if frame < speed then goto wait rem * set speed to a lower number to speed up the snake rem * erase the snake's last segment pfpixel snake_col[4] snake_row[4] off rem * move the snake's segments forward for z = 4 to 1 step 255 y = z - 1 snake_col[z] = snake_col[y] snake_row[z] = snake_row[y] next snake_col[0] = snake_col[0] + snake_e_w snake_row[0] = snake_row[0] + snake_n_s rem * if snake moved "offscreen," then wrap around if snake_col[0] = 255 then snake_col[0] = 31 if snake_col[0] = 32 then snake_col[0] = 0 if snake_row[0] = 255 then snake_row[0] = 10 if snake_row[0] = 11 then snake_row[0] = 0 rem * keep repeating goto loop Note that if you make the snake double back on itself (e.g., let it move left, then press the right arrow so it moves right), the drawing routine above will mess up, since it erases the last segment and draws the new position of the head segment, but doesn't redraw all 5 segments each frame. However, you already said you don't want the snake to be able to double back or cross over itself, so that won't be a problem with the above routine, although you would need to check the pixel for the new position of the head before you actually draw the head there, to be sure it isn't on already (which would mean that either the snake is about to run into a wall, or is about to cross over itself). Michael Rideout
-
That's great! By the way, I was a little off on my row values. If bally is 31, then the ball is straddling rows 3 and 4 (but since row 3 is just "air," the ball is hitting row 4). Any value equal to 31 and a multiple of 8 (i.e., 39, 47, 55, 63, etc.) is straddling two rows. But when bally is 63, the ball is straddling row 7 and row 8 (and row 8 is just "air," so the ball is hitting row 7). So if the ball has collided with the playfield, then: if bally <= 30, the ball hit a wall; if bally >= 31 and bally <= 38, the ball may have hit a brick in row 4; if bally = 39, the ball may have hit a brick in row 4 or row 5; if bally >= 40 and bally <= 46, the ball may have hit a brick in row 5; if bally = 47, the ball may have hit a brick in row 5 or row 6; if bally >= 48 and bally <= 54, the ball may have hit a brick in row 6; if bally = 55, the ball may have hit a brick in row 6 or row 7; if bally >= 56 and bally <= 63, the ball may have hit a brick in row 7; if bally >= 64, the ball hit a wall. If bally < 1, then the ball has moved off the top of the screen, so player 1 (or the top paddle) has missed the ball, and you can set ball_moving to 0. If bally > 89, then the ball has moved off the bottom of the screen, so player 0 (or the bottom paddle) has missed the ball, and you can set ball_moving to 0. Michael Rideout
-
First of all, I like your logo or title screen! However, judging by all the pfpixel commands, it looks like you used the playfield drawing tool to draw your logo and then generate the necessary pfpixel statements. You should be aware that the pf drawing routines take up a lot of machine cycles, and using a lot of pfpixel statements to draw a screen also takes up a lot of ROM. It's almost always much quicker to "poke" the desired playfield data directly into the playfield array, and it can also save a lot of ROM in some cases. Here's another version of your code, which I've modified by removing the pfpixel commands and replacing them with the necessary data and routines to draw the playfield directly. I also replaced your in-line assembly routine to clear the playfield with the equivalent bB code, to show you how you can do that in bB. include div_mul.asm COLUBK = $70 COLUPF = $44 COLUP0 = $C4 programstart gosub clear x = 0 y = 0 end startme gosub clear COLUPF = $44 gosub logo COLUP0 = $00 COLUP1 = $00 : scorecolor = $00 500 g = g + 1 COLUBK = g : COLUP0 = g : COLUP1 = g : COLUPF = $C4 drawscreen if joy0fire then goto programstart goto 500 logo data logo_data %00000000,%00000000,%00000000,%00000000 %00000000,%00000000,%00000000,%00000000 %01111101,%00010111,%11011111,%01111100 %01000101,%10010100,%01000001,%01000100 %01000001,%01010100,%01000010,%01000000 %01111101,%01010111,%11000100,%01110000 %00000101,%01010100,%01001000,%01000000 %01000101,%00110100,%01010000,%01000100 %01111101,%00010100,%01011111,%01111100 %00000000,%00000000,%00000000,%00000000 %00000000,%00000000,%00000000,%00000000 end for r = 0 to 10 for c = 0 to 3 b = 4 * r b = b + c temp1 = logo_data[b] if c = 1 then gosub flip_it if c = 3 then gosub flip_it playfield[b] = temp1 next next return clear for b = 0 to 47 playfield[b] = 0 next return flip_it temp2 = 0 if temp1{0} then temp2{7} = 1 if temp1{1} then temp2{6} = 1 if temp1{2} then temp2{5} = 1 if temp1{3} then temp2{4} = 1 if temp1{4} then temp2{3} = 1 if temp1{5} then temp2{2} = 1 if temp1{6} then temp2{1} = 1 if temp1{7} then temp2{0} = 1 temp1 = temp2 return When your original code is compiled, there are 2002 bytes of ROM free (but you're probably getting a little more than that, because I've added some code to read joystick 1 to one of bB's include files, hence I get less ROM free than you do.) On the other hand, when the modified code is compiled, there are 2587 bytes of ROM free, so using the data statement to define the playfield pixels, and "poking" the data directly into the playfield array using two nested for..next loops, saves 585 bytes of ROM. And I think it's easier to draw the playfield using data statements, because you can more easily see what's being drawn (i.e., by imagining the 0s as blanks and the 1s as playfield pixels that are "on"). However, if you do this, you must flip the second and fourth playfield bytes, since the 2600 reads those bytes "backwards" as it's drawing the playfield, hence I'm calling flip_it to reverse the second and fourth bytes. (The alternative is to store those bytes backwards in the data statements, but that's more difficult to do, so I prefer to store the data in the way that looks natural to the reader's eye, and then use the flip_it routine to reverse the necessary bytes.) As for moving the "snaze" around the screen, you first need to decide what you're going to draw it with-- playfield pixels or player/missile graphics. Assuming that the snaze can be very long, you'll probably want to draw it with playfield pixels, but that's up to you. If you draw the snaze with playfield pixels, then you can use the players and missiles for walls, or for other objects (e.g., "food" that the snaze eats, which makes it grow longer). Either way, you'll want to define one or two variables to indicate and control the directions the snaze is moving in. For example, you could have one variable that can have four or eight different values, corresponding to N, S, E, and W movement (and maybe NE, SE, SW, and NW movement as well, if you want to allow the snaze to move diagonally). You would keep the movement value the same, so the snaze keeps moving in the same direction, and then change the movement value when the joystick or cursor keys are pressed. If you want to use two variables instead of one for the movement, then one variable could control the left/right direction value, and the other variable could control the up/down direction value. Here is a simple example that moves a playfield pixel around: dim snaze_row = a dim snaze_col = b dim snaze_n_s = c dim snaze_e_w = d dim frame = e snaze_row = 5 snaze_col = 16 snaze_n_s = 0 snaze_e_w = 255 COLUBK = $04 COLUPF = $1A loop rem * plot the snaze's position (1 playfield pixel) pfpixel snaze_col snaze_row on rem * draw the screen frame = 0 wait drawscreen rem * update the snaze's direction from the joystick if joy0left then snaze_e_w = 255 : snaze_n_s = 0 if joy0right then snaze_e_w = 1 : snaze_n_s = 0 if joy0up then snaze_n_s = 255 : snaze_e_w = 0 if joy0down then snaze_n_s = 1 : snaze_e_w = 0 rem * wait a bit to slow things down frame = frame + 1 if frame < 10 then goto wait rem * erase the snaze's last position pfpixel snaze_col snaze_row off rem * update the snaze's new position snaze_col = snaze_col + snaze_e_w snaze_row = snaze_row + snaze_n_s rem * if it moved "offscreen," then wrap around if snaze_col = 255 then snaze_col = 31 if snaze_col = 32 then snaze_col = 0 if snaze_row = 255 then snaze_row = 10 if snaze_row = 11 then snaze_row = 0 rem * keep repeating goto loop This example assumes that there will be no diagonal movement, so moving up or down will set the left/right (e/w) movement value to 0, and moving left or right will set the up/down (n/s) movement value to 0. A movement value of 1 will add to the row or column position, moving the snaze down or right. A movement value of 255 will subtract 1 from the row or column position (because 255 is the same as -1), moving the snaze up or left. Of course, this example just moves one playfield pixel around. If the snaze is more than one pixel long, things will be more tricky, because you'll need to leave a "trail" as the snaze moves around, and erase the last pixel, hence you'll need to have variables for remembering the position of the last pixel of the snaze. Also, this example allows the playfield pixel to wraparound from one side of the screen to the other, but presumably you won't want to allow that in your game. Still, I hope this example helps you to see how an object such as a playfield pixel can be moved continuously in a given direction, with the joystick (or cursor keys in an emulator program) being used to steer the object around. Michael Rideout
-
Sorry, it doesn't work that way. batari BASIC programs are written in batari BASIC, and assembly programs are written in assembly. Although you can include assembly code in a batari BASIC program, you can't compile a pure assembly program with batari BASIC-- at least, not really. You *could* write an all-assembly program in batari BASIC and compile it with batari BASIC, but the compiled code will contain all of batari BASIC's included routines, which will take up ROM space. So if you disassemble a .bin file into an .asm file, you don't want to compile it with batari BASIC. Instead, you want to compile it with DASM. batari BASIC does use DASM to compile .asm files into .bin files, but first batari BASIC compiles .bas files into .asm files, and that's the step you'll want to avoid if you're working with a disassembled .asm file. I suggest working directly with the .asm file, using the 6502 assembly language, and then compiling it with DASM once you're done hacking it. However, be aware that disassembled .asm files can be a bit wacky, if Distella tried to disassemble data into assembly commands. (Some parts of an assembly program are data, such as the bytes which define the playfield text display for "The Texas Chainsaw Massacre" title screen, and those data bytes should not be disassembled into assembly commands, since they aren't intended to be assembly commands, and will look extremely wacky if Distella tries to convert them into assembly commands.) The best thing to do, if you're trying to hack a game like TTCM, is check to see if someone else has already disassembled that game. If not, then you will need to figure out which portions of the code are assembly commands, and which portions are data. Then you can create a custom config file for that game, to tell Distella which sections of code are data and should be left as is, and disassemble the game using the custom config file. Then Distella will create an .asm file which has assembly commands where appropriate, and un-disassembled data where appropriate. Once you have such an .asm file, you can try hacking it, and then compile the altered .asm file using DASM. Michael Rideout
