Jump to content
IGNORED

IntyBASIC compiler v1.0 crunchy&tasty :)


Recommended Posts

Also, 30 screens high x 40 screens wide is 360 x 800 tiles, or 288,000 tiles. Unless you have a procedurally generated world or some form of compression, that's going to take a ton of ROM space. It'd fit on an LTO Flash (with page flipping), but not even JLP win its current form will hold it without compression. Compression adds its own challenges.

 

Hm. Good point - I didn't think out the math fully. Even using GROM tiles, you still need a byte to store every single tile. 288KB of world data! Unless you use a small subset of GROM, or get involved with compression etc.

 

Or just not have 1200 unique screens. No idea what kind of game we're talking about, but I could see a lot of re-use of "rooms" or "hallways" or "pathways". Even still, you're talking a lot of repetition if you want to get it down to say 50KB or so. And that's not counting actual game code or other graphic data.

 

Hm. Good point - I didn't think out the math fully. Even using GROM tiles, you still need a byte to store every single tile. 288KB of world data! Unless you use a small subset of GROM, or get involved with compression etc.

 

Or just not have 1200 unique screens. No idea what kind of game we're talking about, but I could see a lot of re-use of "rooms" or "hallways" or "pathways". Even still, you're talking a lot of repetition if you want to get it down to say 50KB or so. And that's not counting actual game code or other graphic data.

 

Well, my point is that all we've discussed is a flat map array, which works for a 2-screen world and maybe even a 50 screen world. But 1200 screens probably needs some higher order organization to be realistic on the Intellivision, most likely.

 

Like you said, reusing at the whole-room level such as hallways and rooms if it's in the dungeon crawl type of game, or with some other compressed representation. I guess we have little to go on at the moment.

Well, I have two screens of background data, and want them to scroll around a "center", in that I don't want a MOB to move, I want the background to move around it. A working example would be the car in Safecracker. How is that done in IntyBASIC?

 

I just wanted to add something that has not been touched on, but was asked in the original question above: apart from scrolling the screen as has already been described by others, you'll have to "move" the MOB in the opposite direction in order to have it stay in place.

 

During scrolling, as the electron gun moves to draw a frame, the STIC (video chip) delays the signal by a number of pixels (horizontal) or raster lines (vertical), effectively shifting the entire video frame down or to the right. Consequently, all MOBs will move naturally with the screen. By adjusting a MOB's position by the same magnitude, but opposite direction, of the shift; you can make it look stationary in relation to the background.

 

This brings an interesting problem: the logical or virtual position of your sprites in relation to the game world is divorced from its physical counterpart in relation to the screen. You'll have to keep this in mind as you track the movements of your sprites.

 

That's the easy part. The hard part is what is already been discussed: how to efficiently and effectively encode the world map and unpack it accordingly for scrolling. Carry on. :)

 

-dZ.

  • Like 1

Good point. The sample scroll.bas code includes the logic necessary for a stationary MOB, but yes - any calculation involving actual MOB position has to take into account these offsets. It's a little weird at first if you're used to calculating things based on MOB position. It's extremely weird when it comes to calculating hit detection.

  • Like 1

It's extremely weird when it comes to calculating hit detection.

 

Well, that depends. If you're doing everything in terms of the coordinates you feed the STIC, then collision detection doesn't change at all, including MOB vs. tile collision.

I have a question about music. The docs say that "#" is for sustain, which is for sharp in other notation. Is that a typo in the docs? In order to quickly/simply translate some songs to the IntyBASIC format, having either sharps or flats (ideally both) is needed. Can someone help me get a clue on that?

 

Thanks.

I have a question about music. The docs say that "#" is for sustain, which is for sharp in other notation. Is that a typo in the docs? In order to quickly/simply translate some songs to the IntyBASIC format, having either sharps or flats (ideally both) is needed. Can someone help me get a clue on that?

 

Thanks.

It's a mistake in the docs. '#' means sharp.

  • Like 2

It's a sharp (nanochess, I thought this was discovered and corrected before the most recent release). Sustain is the MUSIC S,S,- notation.

 

And flats can always be used without specifically calling them such. You just need to remember music theory :)

I believe in Spanish "sharp" note is called "sostenido," which literally means "sustained."

 

Nanochess' code is a worldly polyglot. Get with the program. :)

Sometimes I think both in English and Spanish. :grin:

 

This is corrected in the manual of latest version of IntyBASIC.

  • Like 2

BTW, just I've found a bug in intybasic_prologue.asm

 

The 16-bits variables aren't initialized to zero, in emulator there are no problems, only in real hardware.

 

Replace this to solve it:

 

 

_MAIN0:
        ;
        ; Clean memory
        ;
        MVII #$0fe,R1           ; 240 words of 8 bits plus 14 of sound
        MVII #$100,R4           ; 8-bit scratch RAM
        CALL FILLZERO
        MVII #$058,R1           ; 88 words of 16 bits
        MVII #$308,R4           ; 16-bit scratch RAM
        CALL FILLZERO

 

BTW, just I've found a bug in intybasic_prologue.asm

 

The 16-bits variables aren't initialized to zero, in emulator there are no problems, only in real hardware.

 

Replace this to solve it:

_MAIN0:
        ;
        ; Clean memory
        ;
        MVII #$0fe,R1           ; 240 words of 8 bits plus 14 of sound
        MVII #$100,R4           ; 8-bit scratch RAM
        CALL FILLZERO
        MVII #$058,R1           ; 88 words of 16 bits
        MVII #$308,R4           ; 16-bit scratch RAM
        CALL FILLZERO

 

 

BTW, the EXEC zeros out 8-bit RAM + PSG for you.

 

Also, for folks wanting to check initialization errors (IntyBASIC or otherwise), the --rand-mem flag in jzIntv randomizes memory on "power up."

  • Like 1

BTW, the EXEC zeros out 8-bit RAM + PSG for you.

Am I reading right? could I remove the first three lines without change in behavior?

 

Also, for folks wanting to check initialization errors (IntyBASIC or otherwise), the --rand-mem flag in jzIntv randomizes memory on "power up."

That's a very cool flag! :) I'll try it soon.

 

Also it would mean I could have a 16 bits LFSR very random :) just by not initializing one memory location.

Am I reading right? could I remove the first three lines without change in behavior?

 

 

On second thought maybe you want to erase it anyway. There will be a few variables set by the EXEC by the time you get to MAIN.

 

The EXEC zeros out 8-bit RAM just after checking for ROM at $4800 and $7000. Since IntyBASIC isn't designed to launch from those addresses, then you can rely on the EXEC's wipe.

 

The actual early boot sequence:

.

 $1026:    02BE 02F1              MVII #$02F1,R6        Stack pointer = $2F1                     
 $1028:    0004 0118 0283         JSR  R5,$1A83         Zero out PSG
 $102B:    02B8 0026              MVII #$0026,R0        \
 $102D:    0240 0100              MVO  R0,$0100          |_ Set ISR to $1126                    
 $102F:    02B8 0011              MVII #$0011,R0         |                    
 $1031:    0240 0101              MVO  R0,$0101         /
 $1033:    0001                   SDBD                                       
 $1034:    02B8 0014 0050         MVII #$5014,R0        \_ Set ROM header pointer to $5014
 $1037:    0240 02F0              MVO  R0,$02F0         /
 $1039:    0004 0110 001D         JSR  R5,$101D         \_ Check for ROM at $7000                    
 $103C:    0070                   RRC  R0               /                     
 $103D:    0004 0110 001D         JSR  R5,$101D         \_ Check for ROM at $4800
 $1040:    0048                   SLL  R0               /
 $1041:    02B8 00FE              MVII #$00FE,R0        \
 $1043:    02BC 0102              MVII #$0102,R4         |- Zero memory from $102 to $1FF
 $1045:    0004 0114 0338         JSR  R5,$1738         /

.

I was thinking that zeroing is enough. But then go down one more line:

.

 $1048:    0004 0110 0060         JSR  R5,$1060         Initialize a bunch of variables

   DECLE $035E, $03FF
   DECLE $0147, $0001
   DECLE $0115, $000C
   DECLE $0116, $00A0
   DECLE $0117, $0008
   DECLE $0118, $0060
   DECLE $0119, $0008
   DECLE $0104, $0008
   DECLE $0102, $0084
   DECLE $0000

.

That's what throws a monkey wrench in the works. That table is a sequence of address-value pairs. I'm not sure what else offhand might get touched in 8-bit RAM.

 

So, I rescind my earlier suggestion. :-)

Edited by intvnut
  • Like 1

You mean people don't automatically declare variables to zero as a habit? :P

 

On a couple games I've assisted with, I witnessed (and helped fix) interruptibility bugs because of a wall of MVOs doing exactly that. ie.

.

      CLRR R0
      MVO  R0, Var1
      MVO  R0, Var2
      MVO  R0, Var3
      MVO  R0, Var4
      MVO  R0, Var5
      MVO  R0, Var6
      MVO  R0, Var7
      MVO  R0, Var8
      MVO  R0, Var9
      MVO  R0, Var10
      MVO  R0, Var11
      MVO  R0, Var12
      MVO  R0, Var13
      ;....

.

That's a great recipe to blow a lot of ROM space and generate display glitches. (The display will jump if you issue too many non-interruptible instructions in a row. That includes MVO, PSHR, all shift/swap instructions, SDBD, EIS and DIS.)

 

It's better if you can put all the variables you want cleared next to each other in memory and clear them with a fill loop. IntyBASIC handles this by allocating all the user variables contiguously, and using a fill loop to clear all of the user variables. I think that is an excellent idea.

  • Like 1

That's a great recipe to blow a lot of ROM space and generate display glitches. (The display will jump if you issue too many non-interruptible instructions in a row. That includes MVO, PSHR, all shift/swap instructions, SDBD, EIS and DIS.)

 

I was thinking more along the lines of a zero-ing out at the very beginning of the program. Just best practice and all of that (given that we don't really have functions and variables are all global...). Would this still cause these problems? How much ROM space is a couple hundred declarations?

 

I was thinking more along the lines of a zero-ing out at the very beginning of the program. Just best practice and all of that (given that we don't really have functions and variables are all global...). Would this still cause these problems? How much ROM space is a couple hundred declarations?

 

IntyBASIC guarantees all variables are implicitly initialized to zero after reset with the block fill nanochess mentioned above.

 

If you explicitly zero variables in assembly as per my example above, it's at least 2 words (4 bytes) per variable. In IntyBASIC, I think it blows up to 3 words (6 bytes), since it doesn't "reuse the zero" and does a "CLRR R0 / MVO R0, var" for each variable.

 

That's a bit of a waste if IntyBASIC is already doing the work for you.

 

Of course, if you have a "restart" in your game that needs to zero a bunch of variables, then you don't have a lot of choice.

 

Back when I had to squeeze Space Patrol into 16K words, I actually wrote optimized initializer routines to squeeze the last few bytes out of that ROM. That cartridge was full! (Examples of how it was called can be seen in this file. Just look for for "INIT".)

Edited by intvnut
  • Like 1

What is the useful difference between a 16-bit and 8-bit variable, concerning IntyBASIC? In other words, why would I bother with 16-bit variables at all?

 

Thanks.

Oh, oh, oh! I know this one!!!

 

16-bit variables can hold an unsigned integer value from 0 to 65,553, while an 8-bit variable can only hold from 0 to 255. The range is less for signed values: 32,767 and 127, for 16-bit and 8-bit, respectively.

 

16-bit variables are also useful for pointers, since addresses in the Intellivision memory space are 16-bit.

 

As to why would you bother with a 16-bit variable? It depends on the numeric range you need to store.

 

dZ.

  • Like 2

I thought there might be a "general" (I know, loaded term) difference in runtime speed when using one vs the other after IntyBASIC is compiled into asm. I think I'll have to play with that a bit to understand more. Thanks.

 

Oh, oh, oh! I know this one!!!

16-bit variables can hold an unsigned integer value from 0 to 65,553, while an 8-bit variable can only hold from 0 to 255. The range is less for signed values: 32,767 and 127, for 16-bit and 8-bit, respectively.

16-bit variables are also useful for pointers, since addresses in the Intellivision memory space are 16-bit.

As to why would you bother with a 16-bit variable? It depends on the numeric range you need to store.

dZ.

I thought there might be a "general" (I know, loaded term) difference in runtime speed when using one vs the other after IntyBASIC is compiled into asm. I think I'll have to play with that a bit to understand more. Thanks.

 

 

Ah, no. The only difference is the width. 16-bit variables use what is called "SYSTEM" memory, while 8-bit ones use the "SCRATCH PAD" memory. The stack uses the same "SYSTEM" memory, as does the BACKTAB; while GRAM uses the same type of memory as the SCRATCH.

Adding to the previous comments: The only time you'd end up with a performance difference is if you explicitly stored a 16 bit value in two 8 bit variables. You'd have to manually unpack/repack the data, and that costs cycles.

 

So... variables whose range of values that fit in an 8 bit range, allocate to 8 bit variables. Otherwise, if their range of values fits in a 16-bit range, bump to 16 bit variables. And if you run out of 8-bit variable space, you can always upgrade some variables to 16 bits even if they don't need it. Larger than 16-bits (eg. 32-bit values), and you're on your own to make that arithmetic work, constructed out of 8 or 16 bit variables as you see fit.

One thing to keep in mind is that when you load an 8 bit value into the CP1610, it treats it like a 16 bit number where the upper 8 bits are zero. The number is not sign extended.

 

 

So if you write:

   i = 0 
   i = i -1
   if i < 0 then goto someplace 
noplace:

Your code is going noplace.

 

But if you write:

i = 0 
if (i -1) < 0 then goto someplace 
noplace:

Your code can go someplace.

  • Like 2

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

Loading...
  • Recently Browsing   0 members

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