Jump to content

10-25-08 bAtari Basic build?


Recommended Posts

But no biggie, there are other editors I can use, and I finally got bB working again. :)

Have you tried Visual batari Basic:





Will it work with Windows 98?

It requires the .NET Framework 3.0 and I believe that doesn't work on anything less than Windows XP Service Pack 2.



Link to comment
Share on other sites

Well, I found a way to work around the problem. I put a virtual Windows 98 machine on my computer. bB on that machine works great. :cool:


Crimson Editor on the other hand....The CEDT.EXE file is linked to missing export MFC42.DLL-6877

Even downloading the MFC42.DLL file doesn't make a difference. But no biggie, there are other editors I can use, and I finally got bB working again. :)

You might also have to register the DLL as well. From the commandline try running regsvr32 mfc42.dll.



Link to comment
Share on other sites

I found an even better work-around. Virtual Vista (I'm running it virtually because I don't want to actually use it as my OS).

bB works fine now.

Crimson Editor works fine now.

And finally, I'm going to attempt Visual bB. It didn't for me before, but maybe it will on Vista. Wish me luck. :D

I hope that works because VbB is the best editor for bB I have ever used. It makes programming and working with graphics fun instead of a chore.

Link to comment
Share on other sites

  • 4 weeks later...

Here is a copy of my 2600bas.bat file.


Could someone please add the -O switch and post the updated 2600bas.bat file as an attachment? I would do it myself, but i don't want to mess up my working Batari BASIC installation.


2600 Hero


Edited by 2600 Hero
Link to comment
Share on other sites

  • 1 year later...

Sorry for the late reply (almost two years!), but I must not have seen your questions back when you posted them. :(


Thank you for the detailed explanation. I have a couple of of questions.


When you *define* a macro, it doesn't use up any ROM at all-- but when you *call* a macro, it uses up ROM. A subroutine would be stored in ROM once, and then would use only 3 bytes of ROM each time you call it, and have an overhead of 12 cycles to call it (6 cycles to call it, and 6 cycles to return from it). But a macro always uses up *some* amount of ROM (which could vary each time depending on the circumstances), but it has *no* extra cycles of overhead to call it.


I'm a little confused about what's going on behind the scenes, here. When we compile a program that contains a macro, does the the compiler tally the total number of calls and write them into ROM?

No. When you compile a program that contains a macro, the macro won't be included in the ROM at all unless you actually call it. If you do call it, the macro's code will get inserted into the ROM at every place where you called it. Depending on how the macro is coded, the code that gets added to the ROM may be the same each time (if the macro doesn't use any parameters), or the code may be different but always the same size (if it uses a parameter but the parameter doesn't affect how much code will be inserted), or the code may be completely different (if the macro uses the parameter along with compiler directives to determine what code, and how much code, will be inserted).


I know this sounds confusing, so it may help if you look at some actual macros. And I might add that there are two types of macros-- assembly macros for DASM, and batari Basic macros for the batari Basic compiler. However, the batari Basic compiler will convert any batari Basic macros into assembly macros, which will then be assembled by DASM, so they're really the same thing, with the exception that assembly macros must be coded in assembly, whereas batari Basic macros are coded in batari Basic (but can include inline assembly code).


There are several macros that come "packaged" with DASM (and thus with batari Basic), and they can be found in the "macro.h" file. Open that file to read it, then scroll down until you see "MAC CLEAN_START." This defines a macro for code that initializes all of page zero to 0, clears the stack, and initializes the accumulator and X and Y registers to 0. It uses no parameters, so anytime you call it, DASM will insert the same code into the ROM image. (Note that batari Basic already does this initializing at the beginning of a program, so there's no need for you to ever use this macro yourself unless you aren't using batari Basic's include files.)


Now scroll up a little bit to see the "MAC VERTICAL_SYNC" macro. Again, this macro uses no parameters, so the code is the same whenever you call it. This macro generates the code to do a vertical sync, and uses a method that takes up the smallest number of bytes possible. If you're writing a custom kernel, you can call this macro at the point where you want a vertical sync to be performed, and DASM will insert the proper code in your ROM at that point.


Now scroll down a bit to see the "MAC SET_POINTER" macro. This macro takes two parameters, so each time you call it, the code that gets inserted into your ROM image will be different (unless you call it with the same parameters), but it will always be the same size. What it does is take the lo byte and hi byte of the address you pass it and then store them in two lo-hi pointers at the location you pass it. For example, if you've created a ROM table containing sprite data, you can use this macro to manually set a player's lo-hi pointers to the address of the sprite data.


Now scroll back up to the first macro in the file, "MAC SLEEP." This one is a lot more complicated than the others, because the code it produces will be a different size depending on the parameter you pass it. "SLEEP 2" will generate 1 byte-- a "NOP" command. "SLEEP 3" will generate 2 bytes-- either "NOP 0" or "BIT VSYNC," depending on whether you've set a flag indicating that you don't want to allow "illegal" opcodes like "NOP 0." "SLEEP 4" will generate 2 bytes-- two "NOP" commands. "SLEEP 12" will generate 6 bytes-- six "NOP" commands.


Although these macros are always available (if you've included the "macro.h" file in your assembly, which batari Basic does by default), they won't be included in the ROM unless you call them, so they take up no space unless you call them. The important thing to keep in mind is that when you *do* call them, you don't get a "JSR macro" in your ROM image, you actually get the code that the macro generates. So it's a really bad idea to try to use a large macro that's supposed to function like a subroutine, and then call the macro dozens of times the way you would call a subroutine. But you can define macros that will act like commands, to help simplify the process of coding, as long as it's okay for the macro's code to be inserted wherever it's called. For example, the "SLEEP" macro essentially creates a command that lets you wait for a certain number of machine cycles in situations where code needs to be executed at a precise time, like updating certain graphics registers mid-line. Likewise, the "SET_POINTER" macro creates a command that makes it easier to set a pointer to a particular address.


However, if the statement that calls a macro is just as complex, or even more complex, than the code the macro generates, then it's not a good idea to use the macro. For instance, one of the macros I gave as an example was to set the background color. I used that example because it was pretty simple, and therefore easy to understand, but it's actually a lot easier to just say "COLUBK = $22" instead of "callmacro backgroundcolor $22." For that matter, you could say "dim backgroundcolor = COLUBK," then just say "backgroundcolor = $44" to set the background color-- but the only reason to do that would be if "backgroundcolor" was easier for you to remember than "COLUBK." On the other hand, the "screencolors" macro I gave as an example is somewhat more useful, especially if you rewrite it so it doesn't call any other macros, and so it also sets the score color. Then you could say "callmacro screencolors a b c" to set the background to color "a," set the playfield color to "b," and set the scorecolor to "c." But that would only be useful if you need to set all three colors at once, as opposed to setting just one of them.


By the way, if "callmacro" is kind of long and cumbersome to type, you could use "def do = callmacro" to assign the word "do" to "callmacro." Then you could say "do macro" instead of "callmacro macro." Or you could say "def setcolors = callmacro screencolors" so you could just say "setcolors a b c" to call the "screencolors" macro.


Note that calling a macro in assembly is different, because you don't need a special command to let DASM know that you're calling a macro-- you just use the macro's name, like "SLEEP 6" or "VERTICAL_SYNC." In batari Basic, you need to use "callmacro SLEEP 6" or "callmacro VERTICAL_SYNC," so the batari Basic compiler will understand that you're calling a macro.


I assume one shouldn't do even do this, but how would the compiler handle a macro in a looping or iterative statement, such as:


  dim my_var = a

 macro my_macro
 missile0x = {1}

 my_var = my_var + 1
 callmacro my_macro my_var
goto myLoop

Passing a variable to a macro (as opposed to a constant, or a symbolic name that represents a constant) is tricky, because the macro would need to be coded so it treats the parameter as a variable. I think the example you gave should work, although it would be much simpler to just say "missile0x = my_var" instead of "callmacro my_macro my_var." Some macros won't work if you send them a variable. For example, you couldn't put "SLEEP my_var" in a loop (or even use it at all), because DASM can't generate different code for the "SLEEP" macro each time you go through the loop, and the "SLEEP" macro isn't designed to work with a variable as the parameter. On the other hand, you *can* put a "SLEEP 6" statement inside a loop, because when DASM makes its first pass through the code, it will replace "SLEEP 6" with three "NOP" commands, and that's what will be executed each time you go through the loop-- three "NOP" commands.


Also, I'm a little confused by the use of "{#}" in the below definitions and calls. What happens when the program executes "callmacro backgroundcolor {2}."


You can't *define* a macro inside the definition of another macro, but you can *call* an already-defined macro inside the definition of another macro. For example:


   macro backgroundcolor
  COLUBK = {1}

  macro playfieldcolor
  COLUPF = {1}

  macro screencolors
  callmacro playfieldcolor {1}
  callmacro backgroundcolor {2}

As may be clear by now (or hopefully getting clearer), the program won't actually execute "callmacro backgroundcolor {2}" when it's running. The batari Basic compiler will replace the "callmacro backgroundcolor {2}" statement with the assembly equivalent of "COLUBK = {1}," and that's what will be executed by the program. As I already stated, those weren't very good examples, because it's actually easier to just say "COLUBK = my_var," or "COLUBK = $color." But as far as one macro calling another, any parameters you pass to the first macro will be {1}, {2}, {3}, etc. If that macro calls another macro, it can pass one or more of those parameters to the other macro. To the second macro, the parameters will then become {1}, {2}, {3}, etc., depending on the order they were passed in.


For example, if you say "callmacro screencolors $C8 $02," {1} will be $C8, and {2} will be $02. The batari Basic compiler will replace that statement with


  callmacro playfieldcolor $C8
  callmacro backgroundcolor $02

Then $C8 will become {1} for the "playfieldcolor" macro, and $02 will become {1} for the "backgroundcolor" macro. The batari Basic compiler will then replace those two statements with


  COLUPF = $C8
  COLUBK = $02

And finally, the batari Basic compiler will replace *those* statements with assembly code:


  LDA #$C8
  LDA $02

*That* is the code that will actually appear in your ROM at the place where you said "callmacro screencolors $C8 $02."


The thing is, macros can be very powerful and useful, helping to simplify the process of coding a game-- but only if calling the macros isn't less efficient than simply putting in the code that they generate. For example, "SLEEP 2" takes longer to type than "NOP" does, so in that sense it's actually less efficient than simply using "NOP" instead of "SLEEP 2." On the other hand, "SLEEP 2" is easier to change in your code. For example, if you aren't sure how long you need to wait, you might put "SLEEP 2" in your code to start with. After you assemble your code and run it, you might see that "SLEEP 2" doesn't wait long enough, so you can change it to "SLEEP 3," then "SLEEP 4," then "SLEEP 5," etc., until you find the right number.


Also, the code that a macro generates might not be optimized for space. For example, "SLEEP 24" will be replaced by 12 "NOP" commands. The most optimized way to wait for 12 cycles is to do a "JSR" to a "RTS," as follows:


  ; wait for 12 cycles
  JSR sleep12
  LDA #$98
  ; etc.

  ; ...


So to sleep for 24 cycles, you could say


  JSR sleep12
  JSR sleep12
  ; etc.


Note that "sleep12" isn't a macro, just a subroutine. It takes 4 bytes instead of 6, but it could take only 3 bytes if the "RTS" is at the end of another subroutine:


  JSR sleep12 ; 3 bytes
  ; etc.

  ; some code here
  RTS ; this returns from "subroutine," but also returns from "sleep12"

Then, if you need to wait 14 cycles, you could do this:


  JSR sleep12

I used this sort of thing a lot in the "E.T. Book Cart" in places where I needed to sleep for large amounts of time. For example,


  JSR sleep30
  ; etc.

  JSR sleep18


will wait for 30 cycles, and uses only 11 bytes in all, whereas "SLEEP 30" would have used 15 bytes. Plus, it really takes less bytes than that to define the three "sleep" subroutines, and once you define them you can call them as often as you need. The more you call them, the more bytes you save overall.



Edited by SeaGtGruff
Link to comment
Share on other sites

Join the conversation

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

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

  • Recently Browsing   0 members

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