Jump to content
IGNORED

Assembly BYTE and more questions


jchase1970

Recommended Posts

A few pieces of code for question reference,

 

JOYY EQU >8376

JOYUP BYTE 4,0

START BLWP @KSCAN

C @JOYY,@JOYUP

 

 

ok this is of course apart of a joystick reading example, which I understand. My question is on the Byte opcode. I looked around the manual and didn't find a answer so here is the best place to ask.

 

JOYUP BYTE 4,0

I'm assuming that it is assigning 2 bytes to the label JOYUP?

How many bytes can you assign to a label like this?

 

C @JOYY,@JOYUP

this compares values in the addresses starting at >8376 to the byte values in JOYUP 4,0?

So since JOYUP contains 2 bytes 4,0, it checks 2 addresses >8376 and >8377?

 

 

Had I not had this example I would have done 2 compares, one for JOYY and one for JOYX,ie

JOYY EQU >8376

JOYX EQU >8377

JOYUPY BYTE 4

JOYUPX BYTE 0

START BLWP @KSCAN

C @JOYY,@JOYUPY

JNE *

C @JOYX,@JOYUPX

 

But I guess I would have been doing it the hard way. I guess it's no different then when I have a label for a pattern and a DATA with 4 WORDs. It just seemed strange to me to see it done that way. I guess since I seem to know what it's doing is how many bytes I can assign this way. I Did read that DATA can have a max of 4 WORDs, but like I said I didn't find anything on BYTE.

 

John

Edited by jchase1970
Link to comment
Share on other sites

JOYUP BYTE 4,0

I'm assuming that it is assigning 2 bytes to the label JOYUP?

How many bytes can you assign to a label like this?

 

Not exactly. BYTE is a compiler directive, not an opcode. What it's doing is declaring values, expressed in byte form, at that particular location in memory, rather like the DATA statement in BASIC. The compiler assigns the label "JOYUP" to apply to that specific starting address.

 

The only limit on how many bytes you can have is how much memory the system has. :)

 

They could also have done it like this:

 

JOYUP DATA >0400

 

Or this:

 

JOYUP DATA 1024

 

And it would be identical in behavior.

 

C @JOYY,@JOYUP

this compares values in the addresses starting at >8376 to the byte values in JOYUP 4,0?

So since JOYUP contains 2 bytes 4,0, it checks 2 addresses >8376 and >8377?

 

Yes. The C opcode compares words, not bytes.

 

Had I not had this example I would have done 2 compares, one for JOYY and one for JOYX,ie

JOYY EQU >8376

JOYX EQU >8377

JOYUPY BYTE 4

JOYUPX BYTE 0

START BLWP @KSCAN

C @JOYY,@JOYUPY

JNE *

C @JOYX,@JOYUPX

 

But I guess I would have been doing it the hard way. I guess it's no different then when I have a label for a pattern and a DATA with 4 WORDs. It just seemed strange to me to see it done that way. I guess since I seem to know what it's doing is how many bytes I can assign this way. I Did read that DATA can have a max of 4 WORDs, but like I said I didn't find anything on BYTE.

 

They're compiler directives, so the limitations are actually determined by the compiler. The TI compiler does cut things off after a particular point, so it's better to keep it to 4 words or 8 bytes just to keep things clean.

 

The A99 compiler, for example, has no such limitations, and I had code source that compiled fine in it but had all sorts of weird compiler errors on the TI. I investigated and found it was truncating some of my DATA and BYTE lines that had "passed" in A99.

 

Adamantyr

Link to comment
Share on other sites

The other thing to remember about the "word" based instructions, like C, MOV, etc. are that they will *ALWAYS* do their work on 16-bit values (two bytes) and *ALWAYS* on even addresses. If your "JOYY BYTE 4,0" label ended up on an odd address (which can happen with the BYTE directive), the C instruction would be comparing against the wrong data. There is an "EVEN" directive if you need to make sure your labels or other code start on even addresses.

 

Matthew

Link to comment
Share on other sites

The other thing to remember about the "word" based instructions, like C, MOV, etc. are that they will *ALWAYS* do their work on 16-bit values (two bytes) and *ALWAYS* on even addresses. If your "JOYY BYTE 4,0" label ended up on an odd address (which can happen with the BYTE directive), the C instruction would be comparing against the wrong data. There is an "EVEN" directive if you need to make sure your labels or other code start on even addresses.

 

Matthew

 

 

Ahh, EVEN was used in the example, I never even thought about what it was doing, thanks for bringing that extra detail out.

 

John

Link to comment
Share on other sites

Ok, I'm putting in my joystick code, and right now I just have it drawing the 16x16 sized sprites on the screen and then testing the joystick by printing left or right, my only joystick functions,

 

LOOP    BLWP @KSCAN
       CB   @JOYX,@JOYRT
       JEQ  P1
       CB   @JOYX,@JOYLT
       JEQ  P2
       B    @LOOP
P1      LI R1,RT
       JMP @PRINT
P2      LI R1,LT
       JMP @PRINT
PRINT   LI R0,138
       LI R2,10
       BLWP @VMBW
       B   @LOOP
       END START

 

So it works fine, displays left or right depending on which way the joystick is pressed, but......

 

I pressed the button on the joystick and it turns my sprites back into 8x8 sprites instead of the 16x16 sprites. There is no condition here for any other function but left/right. Everything is localized to this small loop? Any ideas?

 

LI R0,>01E2 *set sprites to double size

BLWP @VWTR

this is the code to set the sprites to doublesized, I'm thinking the only way to set it back to singlesized sprite is to write >0100 to VWTR R0?

Edited by jchase1970
Link to comment
Share on other sites

Ok, I'm putting in my joystick code, and right now I just have it drawing the 16x16 sized sprites on the screen and then testing the joystick by printing left or right, my only joystick functions,

 

LOOP    BLWP @KSCAN
       CB   @JOYX,@JOYRT
       JEQ  P1
       CB   @JOYX,@JOYLT
       JEQ  P2
       B    @LOOP
P1      LI R1,RT
       JMP @PRINT
P2      LI R1,LT
       JMP @PRINT
PRINT   LI R0,138
       LI R2,10
       BLWP @VMBW
       B   @LOOP
       END START

 

So it works fine, displays left or right depending on which way the joystick is pressed, but......

 

I pressed the button on the joystick and it turns my sprites back into 8x8 sprites instead of the 16x16 sprites. There is no condition here for any other function but left/right. Everything is localized to this small loop? Any ideas?

 

LI R0,>01E2 *set sprites to double size

BLWP @VWTR

this is the code to set the sprites to doublesized, I'm thinking the only way to set it back to singlesized sprite is to write >0100 to VWTR R0?

 

 

The KSCAN routine is writing to the REG for you ;-) Part of the screen saver function. There is a location in scratch pad that you need to write E2 to to prevent this. It's in the manual (sorry don't have it right now.) I wonder why the joysticks don't trigger this ?

Link to comment
Share on other sites

Ok, I'm putting in my joystick code, and right now I just have it drawing the 16x16 sized sprites on the screen and then testing the joystick by printing left or right, my only joystick functions,

 

LOOP    BLWP @KSCAN
       CB   @JOYX,@JOYRT
       JEQ  P1
       CB   @JOYX,@JOYLT
       JEQ  P2
       B    @LOOP
P1      LI R1,RT
       JMP @PRINT
P2      LI R1,LT
       JMP @PRINT
PRINT   LI R0,138
       LI R2,10
       BLWP @VMBW
       B   @LOOP
       END START

 

So it works fine, displays left or right depending on which way the joystick is pressed, but......

 

I pressed the button on the joystick and it turns my sprites back into 8x8 sprites instead of the 16x16 sprites. There is no condition here for any other function but left/right. Everything is localized to this small loop? Any ideas?

 

LI R0,>01E2 *set sprites to double size

BLWP @VWTR

this is the code to set the sprites to doublesized, I'm thinking the only way to set it back to singlesized sprite is to write >0100 to VWTR R0?

 

There's nothing wrong with your code, you just didn't know one small detail.

 

The contents of VDP register 1 are mirrored in the scratch-pad at @>83D4. During the interrupt stage, it recopies the value at 83D4 into register 1. So if you alter register 1 (which conveniently contains the sprite settings for size) you have to also copy the same value into 83D4 to ensure it doesn't get reset back to it's original value.

 

Adamantyr

Link to comment
Share on other sites

Well, I did this

       LI R0,>01E2 *set sprites to double size
       BLWP @VWTR
       MOV R0,@>83D4 

compiled it and ran it and... now when the button is pressed the screen goes blank. So what am I not understanding? I don't have to rewrite VDP R1 every loop cycle do I?

 

PS the manual doesn't mention anything about this when it in the sprite section that I can find anyways. I found in the example at 21.7.3 where it talks about limi 0 to prevent the program from changing vdp registers which are used by sprite motion. So I tried disabling the interrupts but that didn't seem to work for me either.

Link to comment
Share on other sites

Well, I did this

       LI R0,>01E2 *set sprites to double size
       BLWP @VWTR
       MOV R0,@>83D4 

 

That's because you used MOV, which is a "word" move, so you wrote >01 to >83D4 and >E2 to >83D5. By the way page 406 of the E/A manual details the use of these bytes.

 

Now, you probably wanted to actually write >E2 to >83D4, but you wrote >01, which has the effect of setting the VDP RAM to 4K, blanking the screen, disabling the VDP interrupt, setting graphics mode 1 or 2, setting sprites to size 8x8, and magnification to 2X:

 

>01         0       0       0       0       0       0       0       1
>E2         1       1       1       0       0       0       1       0
       +-------+-------+-------+-------+-------+-------+-------+-------+
REG-1 : | 4/16K | BLANK |  IE   |   M1  |   M2  |   0   |  SIZE |  MAG  |
       +-------+-------+-------+-------+-------+-------+-------+-------+
  bit:     0       1       2       3       4       5       6       7

BIT 0    4/16K selection
          0 selects 4027 RAM operation
          1 selects 4108/4116 RAM operation

BIT 1    BLANK enable/disable
          0 causes the active display area to blank
          1 enables the active display
          Blanking causes the display to show border color only

BIT 2    IE (Interrupt Enable)
          0 disables VDP interrupt
          1 enables VDP interrupt

BIT 3,4  M1, M2 (mode bits 1 and 2)
        M1, M2 and M3 determine the operating mode of the VDP:

          M1  M2  M3
          0   0   0   Graphics I mode
          0   0   1   Graphics IO mode
          0   1   0   Multicolor Mode
          1   0   0   Text mode

BIT 5    Reserved

BIT 6    Size (sprite size select)
          0 select Size 0 sprites (8x8 bit)
          1 select Size 1 sprites (16x16 bits)

BIT 7    MAG (Magnification option for sprites)
          0 selects MAG0 sprites (1X)
          1 selects MAG1 sprites (2X)

 

What you probably want to do is this:

 

       LI   R0,>01E2 *set sprites to double size
       BLWP @VWTR
       SWPB R0
       MOVB R0,@>83D4

 

Or, if you defined where your workspace is, then you can use a label to reference R0's low byte directly:

 

MYWS    EQU  >8300
R0LB    EQU  MYWS+1
.
.
.
       LWPI MYWS
.
.
.
       LI   R0,>01E2 *set sprites to double size
       BLWP @VWTR
       MOVB @R0LB,@>83D4

 

Matthew

Edited by matthew180
Link to comment
Share on other sites

Also, in your code, the JMP @PRINT after P2 is not necessary:

 

LOOP    BLWP @KSCAN
       CB   @JOYX,@JOYRT
       JEQ  P1
       CB   @JOYX,@JOYLT
       JEQ  P2
       B    @LOOP
P1      LI R1,RT
       JMP @PRINT
P2      LI R1,LT
       JMP @PRINT    <------- this is not needed
PRINT   LI R0,138
       LI R2,10
       BLWP @VMBW
       B   @LOOP
       END START

 

You can also get rid of the P1 and P2 labels, and make things a little smaller by setting a default (assume RT text):

 

LOOP
       LI   R1,RT        ; Assume right text
       BLWP @KSCAN
       CB   @JOYX,@JOYRT ; Test for right
       JEQ  PRINT        ; If right, just print (already set up by default)
       CB   @JOYX,@JOYLT ; Test for left
       JNE  LOOP         ; Not left, go back and test joystick again
       LI   R1,LT        ; Set left text
PRINT   
       LI   R0,138
       LI   R2,10
       BLWP @VMBW
       JMP  LOOP         ; Changed from B @LOOP to JMP.
       END  START

 

The B instruction is 4 bytes, the JMP is only 2 bytes. B and JMP do the same thing except the "range" of JMP is only +/- 256 addresses, where the B instruction can branch to any address in the 64K range of the CPU. The assembler will tell you if your JMP is "out of range".

 

Matthew

Link to comment
Share on other sites

       LI   R0,>01E2 *set sprites to double size
       BLWP @VWTR
       SWPB R0
       MOVB R0,@>83D4

 

SWPB R0 switches >01E2 to >E201

 

MOVB R0,@>83D4 only moves the first byte >E2 to the memory location?

 

Is the first byte in a word low or high?

 

First byte (left) is the high byte, second byte (right) is the low byte. Yes, we know, it's NOT how modern PC's are. It's Big-Endian instead of little-Endian. They call it "Motorola" style these days as opposed to "Intel", at least in my hex editor application.

 

If you need to do things on non-even addresses, you must use byte commands like CB, MOVB, etc. The word operations NEVER do anything with odd addresses, if you try and force them they just round down to the even address. This is because the address line is, literally, only 15-bits.

 

Adamantyr

Link to comment
Share on other sites

On the 9900 CPU (which is big-endian), the MSB (most significant byte, not to be confused with the MSb (most significant *bit*)) is the left most byte in a 16-bit word:

 


TI Bit Numbering:
Memory Address:   >xxx0             >xxx1
            +----------------+----------------+
16-bit Word  |0 2 3 4 5 5 6 7   8 9 A B C D E F|
            +----------------+----------------+
8-bit Bytes  |0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7|
            +----------------+----------------+
                  MSB                LBS


Rest of the World:
Memory Address:   >xxx0             >xxx1
            +----------------+----------------+
16-bit Word  |F E D C B A 9 8 | 7 6 5 4 3 2 1 0|
            +----------------+----------------+
8-bit Bytes  |7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0|
            +----------------+----------------+
                  MSB                LBS

 

*NOTE*

Bit "numbering" does NOT affect the bit's place value. It is just how the bits are referenced. Bit "values", just like in our decimal system, start on the right and get larger as you go to the left.

 

Big-endian computers store the MSB in the lowest address, which in the 16-bit 9900 is the EVEN address. In the 9900 CPU, the byte instructions when dealing with a register as a parameter, use the MSB. ALL word instructions will *always* deal with 16-bit values, and if you try to specify an odd address, it will use the lower even address as the MSB, and the odd address as the LSB.

 

* Moves the 16-bit value at >0000 to >000E
      MOV @>0001,>000E

The byte at >0000 (MSB) goes to >000E
The byte at >0001 (LSB) goes to >000F

 

Little-endian computers, like the x86 processors, store the LSB in the lower addresses, i.e. in a reverse order than big-endian computers. Neither is really better than the other, but like programming languages, computer systems, etc. people love to argue the merits of one over the other, why this is better than that, etc. As a programmer you just need to know the difference and how to work with either. So, for our 9900 CPU, MSB is at the lower address and appears in MSB-LSB order in memory.

 

Matthew

Edited by matthew180
Link to comment
Share on other sites

See that's why I choose MOV, thinking I was moving into a even address 83D4 that I needed to move a word. It just never dawned on me that I needed to move a byte. But had it dawned on me to move a byte I would have probably moved the wrong one.

 

Thanks guys, really! I'm really learning alot here right now.

 

John

Link to comment
Share on other sites

If I want to modify the X value of a SAT, how best to do this.

 

I can think of 2 ways to do it,

 

1 load the value from VDPRAM, modify it, write it back

2 EQU a label to the original value, then when needed modify this labels value and write it to VDPRAM

 

I'm having a little trouble getting it to work, I think cause the X value is the low byte. Can I write a byte just to the low byte, ie

 

say i set the SAT here

SAT EQU >300

then later I define a sprite

BIN DATA >AB40,>A009

LI R0,SAT

LI R1,BIN

LI R2,4

BLWP @VMBW

 

Now can I load the just the >40 low byte of the 1st word by doing a BLWP @VSBR maybe like this.

LI R0,SAT+1

BLWP @VSBR

or will this not work because it's the low byte?

 

If it does work, can I write it back the same way like this,

assuming it does work it store the value in R1 and I modify and store it back in R1 and write,

LI R0,SAT+1

BLWP @VSBW

Link to comment
Share on other sites

Now can I load the just the >40 low byte of the 1st word by doing a BLWP @VSBR maybe like this.

LI R0,SAT+1

BLWP @VSBR

or will this not work because it's the low byte?

 

If it does work, can I write it back the same way like this,

assuming it does work it store the value in R1 and I modify and store it back in R1 and write,

LI R0,SAT+1

BLWP @VSBW

 

Yep, that works fine. The VDP is an 8-bit system, and you're going through an 8-bit memory-mapped port, so there's no even addressing issues.

 

What I did find myself was that sprite attribute changes often involved single words, so I did end up writing a VSWW and VSWR routine, so I wouldn't have to keep loading R2.

 

Adamantyr

Link to comment
Share on other sites

ok, so I left off yesterday trying to modify my SAT x value, I gave up and went to bed. This morning I just wrote a new short program with 1 sprite and joystick and commented it all out, looks like it should work but, I guess I'm not doing something right. Please glance at it and see what i'm not doing.

 

It loads the sprite pattern and draws the sprite on screen, I can't move the sprite. So I'm either not INC or DEC the value in R1 returned from VSBR or I'm not writing it back after it's modified.

 

      DEF  START
      REF VMBW,VWTR,VSBR,VSBW,KSCAN
SAT    EQU  >300
SDT    EQU  >400
KBPARD EQU  >8374
JOYX   EQU  >8377

ONE    BYTE 1
JOYRT  BYTE 4
JOYLT  BYTE -4

PAD    DATA >0,>0,>0,>FFFF
      DATA >0,>0,>0,>0
      DATA >0,>0,>0,>FFFF
      DATA >0,>0,>0,>0

P1     DATA >A040,>8001,>D000

*LOAD WORKSPACE
MYREG  BSS  >20
START  LWPI MYREG

*double sized sprites
      LI   R0,>01E2
      BLWP @VWTR
      SWPB R0          *SET >E2 TO HIGH BYTE
      MOVB R0,@>83D4   *SET VDP R1 BACKUP BYTE TO >E2

*LOAD SPRITE PATTERNS
      LI   R0,SDT      *1ST PATTERN IN TABLE
      LI   R1,PAD      *PAD DATA
      LI   R2,32       *DATA IS 32 BYTES LONG
      BLWP @VMBW
      LI   R0,SDT+32   *2ND PATTERN IN TABLE
      LI   R1,BALL     *BALL TABLE
      BLWP @VMBW       *R2 STILL SET TO 32 SO WRITE

*SET SPRITES
      LI   R0,SAT      *1ST SPRITE
      LI   R1,P1       *SPRITE IS PLAYER
      LI   R2,6        *4BYTES OF INFO
      BLWP @VMBW

LOOP   BLWP @KSCAN M      *SCAN LEFT SIDE KEYBOARD AND JOYSTICK 1
      CB   @JOYX,@JOYRT  *SEE IF JOYSTICK IS RT
      JEQ  RT            *IF SO JUMP TO MOVE PAD RIGHT
      CB   @JOYX,@JOYLT  *SEE IF JOYSTICK IS LEFT
      JEQ  LT            *IF SO GO HERE
      B    @LOOP         *NO JOYSTICK MOVEMENT BRANCH TO LOOP

RT     LI   R0,SAT+1      *LOAD PLAYER X POS ADDRESS
      BLWP @VSBR         *READ THE ADDRESS
*                         *R1 CONTAINS VALUE
      CI   R1,224        *MAX RT 
      JEQ  LOOP          *IF MAX JMP OUT
      INC  R1            *INCREASE VALUE BY 1
      BLWP @VSBW         *WRITE IT BACK
      B    @LOOP         *BRANCH BACK TO LOOP

LT     LI   R0,SAT+1      *LOAD PLAYER X POS ADDRESS
      BLWP @VSBR         *READ THE ADDRESS
*                         *R1 CONTAINS VALUE
      CI   R1,0          *MIN RT 
      JEQ  LOOP          *IF MIN JMP OUT
      DEC  R1            *DECREASE VALUE BY 1
      BLWP @VSBW         *WRITE IT BACK
      B    @LOOP         *BRANCH BACK TO LOOP

      END  START

Edited by jchase1970
Link to comment
Share on other sites

Got a message from Insane.multi about this, suggesting I swpb the bytes because VSBW is writing the high byte so I did this, but still no luck.

 

RT     LI   R0,SAT+1      *LOAD PLAYER X POS ADDRESS
      BLWP @VSBR         *READ THE ADDRESS
*                         *R1 CONTAINS VALUE
      CI   R1,224        *MAX RT 
      JEQ  LOOP          *IF MAX JMP OUT
      INC  R1            *INCREASE VALUE BY 1
      SWPB R1            *SET HIGH BYTE TO VALUE I WANT TO WRITE
      BLWP @VSBW         *WRITE IT BACK
      B    @LOOP         *BRANCH BACK TO LOOP

Link to comment
Share on other sites

Try this

 

RT     LI   R0,SAT+1      *LOAD PLAYER X POS ADDRESS
      CLR  R1
      BLWP @VSBR         *READ THE ADDRESS
*                         *R1 CONTAINS VALUE IN HIGH BYTE
      SWPB R1            *SWAP HIGH AND LOW BYTE
      CI   R1,224        *MAX RT 
      JEQ  LOOP          *IF MAX JMP OUT
      INC  R1            *INCREASE VALUE BY 1
      SWPB R1            *SWAP HIGH AND LOW BYTE
      BLWP @VSBW         *WRITE IT BACK
      B    @LOOP         *BRANCH BACK TO LOOP

Edited by sometimes99er
Link to comment
Share on other sites

ok, I got it to work, I did the same thing sometimes suggested, after I reread about VSBR and VSBW in the manual. But it still didn't work, the I seen sometimes post and he had the CLR R1 line I didn't have, but it still didn't work, so I re examined the rest of the code thinking it had to be some place else and it was.

 

I never set the keyboard value if 1

MOVB @ONE,@KBOARD

So I just I was never reading anything with the KSCAN.

 

I was going nuts over this, thanks for all the help again.

Link to comment
Share on other sites

The code from the last problem, now working if anyone wants to see it,

 

      DEF  START
      REF VMBW,VWTR,VSBR,VSBW,KSCAN
SAT    EQU  >300
SDT    EQU  >400
KBOARD EQU  >8374
JOYX   EQU  >8377

ONE    BYTE 1
JOYRT  BYTE 4
JOYLT  BYTE -4



BALL   DATA >3C7E,>FFFF,>FFFF,>7E3C
      DATA >0,>0,>0,>0
      DATA >0,>0,>0,>0
      DATA >0,>0,>0,>0

PAD    DATA >0,>0,>0,>FFFF
      DATA >0,>0,>0,>0
      DATA >0,>0,>0,>FFFF
      DATA >0,>0,>0,>0

P1     DATA >A040,>8001,>D000
B1     DATA >C040,>8401

*LOAD WORKSPACE
MYREG  BSS  >20
START  LWPI MYREG

*double sized sprites
      LI   R0,>01E2
      BLWP @VWTR
      SWPB R0          *SET >E2 TO HIGH BYTE
      MOVB R0,@>83D4   *SET VDP R1 BACKUP BYTE TO >E2

      MOVB @ONE,@KBOARD


*LOAD SPRITE PATTERNS
      LI   R0,SDT      *1ST PATTERN IN TABLE
      LI   R1,PAD      *PAD DATA
      LI   R2,32       *DATA IS 32 BYTES LONG
      BLWP @VMBW
      LI   R0,SDT+32   *2ND PATTERN IN TABLE
      LI   R1,BALL     *BALL TABLE
      BLWP @VMBW       *R2 STILL SET TO 32 SO WRITE

*SET SPRITES
      LI   R0,SAT      *1ST SPRITE
      LI   R1,P1       *SPRITE IS PLAYER
      LI   R2,6        *4BYTES OF INFO
      BLWP @VMBW

LOOP   BLWP @KSCAN M      *SCAN LEFT SIDE KEYBOARD AND JOYSTICK 1
      CB   @JOYX,@JOYRT  *SEE IF JOYSTICK IS RT
      JEQ  RT            *IF SO JUMP TO MOVE PAD RIGHT
      CB   @JOYX,@JOYLT  *SEE IF JOYSTICK IS LEFT
      JEQ  LT            *IF SO GO HERE
      B    @LOOP         *NO JOYSTICK MOVEMENT BRANCH TO LOOP

RT     LI   R0,SAT+1      *LOAD PLAYER X POS ADDRESS
      CLR  R1            *CLEAR BOTH HI AND LOW BYTES OF R1
      BLWP @VSBR         *READ THE ADDRESS
      SWPB R1            *SET HIGH BYTE TO LOW BYTE THAT I NEED
*                         *R1 HIGH BYTE CONTAINS VALUE
      CI   R1,224        *MAX RT
      JEQ  LOOP          *IF MAX JMP OUT
      INC  R1            *INCREASE VALUE BY 1
      SWPB R1            *SET LOW BYTE BACK TO HIGH BYTE FOR THE WRITE
      BLWP @VSBW         *WRITE IT BACK
      B    @LOOP         *BRANCH BACK TO LOOP

LT     LI   R0,SAT+1      *LOAD PLAYER X POS ADDRESS
      CLR  R1
      BLWP @VSBR         *READ THE ADDRESS
*                         *R1 CONTAINS VALUE HIGH BYTE
      SWPB R1
      CI   R1,0          *MIN RT
      JEQ  LOOP          *IF MIN JMP OUT
      DEC  R1            *DECREASE VALUE BY 1
      SWPB R1
      BLWP @VSBW         *WRITE IT BACK
      B    @LOOP         *BRANCH BACK TO LOOP

      END  START

Edited by jchase1970
Link to comment
Share on other sites

I suggest that instead of reading the VDP to get the current location of a sprite, maintain the sprite's x,y location in your own variables and simply do updates to the VDP when the sprite moves. If you think of the display and sprite locations as "write only", you will have a much easier time making your games. Since the VDP only has a single byte for each x and y location, it only costs you two bytes of memory in your program. Actually, you are already using the memory in your data at the P1 label, so use it!

 

SAT    EQU  >0300
SP0SAT EQU  SAT
SP1SAT EQU  SAT+4
SP2SAT EQU  SAT+8

* Make some common byte values to make adding and subtracting easier
NUM1   BYTE 1         ; Byte value 1
NEG1   BYTE -1        ; Byte value -1

* Boundaries
XMAX   BYTE 230
XMIN   BYTE 8

* Sprite data
P1SP   DATA SP0SAT    ; Sprite 0 used by player 1
P1Y    BYTE 96        ; Player 1 Y (192 / 2)
P1X    BYTE 128       ; Player 1 X (256 / 2)
P1N    BYTE 128       ; Player 1 pattern "name" (character)
P1C    BYTE 1         ; Player 1 color in low 4-bits

.
.
.

*SET SPRITES
      LI   R0,P1SP     * Player 1 SPRITE
      LI   R1,P1Y      * Sprite data order is Y,X,N,C
      LI   R2,4        * 4 bytes for the sprite
      BLWP @VMBW

      LI   R0,SP1SAT   * Sprites 1 to 31 will be disabled
      LI   R1,>D000    * Write >D0 to the Y value of the first unused sprite  
      BLWP @VSBW
.
.
.

RT     
      AB   @NUM1,@P1X    ; Increment Player 1 X
      CB   @P1X,XMAX     ; Range check
      JLE  RTLTX         ; Unsigned Jump if Low or Equal
      MOVB @XMAX,@P1X    ; Clamp X to max boundary
      JMP  RTLTX         ; Jump to update code

LT     
      AB   @NEG1,@P1X    ; Decrement Player 1 X
      CB   @P1X,XMIN     ; Range check
      JHE  RTLTX         ; Unsigned Jump if High or Equal
      MOVB @XMIN,@P1X    ; Clamp X to min boundary

* Right / Left X update
RTLTX
      LI   R0,P1SP+1     ; Address for X data
      MOVB @P1X,R1       ; Put P1X into MSB of R1 for writing
      BLWP @VSBW         ; Write updated X location to VDP
      JMP  LOOP          ; "JUMP" back to loop

 

 

Also, you are setting your work space to 8-bit RAM, and that is bad. You should always load the workspace pointer somewhere in the 256 bytes of 16-bit memory:

 

*LOAD WORKSPACE
MYREG  BSS  >20       <--- reserves 32 bytes which will be in 8-bit memory
START  LWPI MYREG     <--- Sets the workspace pointer to the 8-bit memory address


MYWS   EQU  >8300
.
.
.
START
      LWPI MYWS      <--- Set the workspace pointer to >8300, which is the start of the 256 bytes of 16-bit RAM

 

Also, once you get things working, you might want to have a look at my assembly thread about how to dump the VDP routines for your own faster ones. I hope some of this helps.

 

Matthew

Link to comment
Share on other sites

I suggest that instead of reading the VDP to get the current location of a sprite, maintain the sprite's x,y location in your own variables and simply do updates to the VDP when the sprite moves. If you think of the display and sprite locations as "write only", you will have a much easier time making your games. Since the VDP only has a single byte for each x and y location, it only costs you two bytes of memory in your program. Actually, you are already using the memory in your data at the P1 label, so use it!

 

SAT    EQU  >0300
SP0SAT EQU  SAT
SP1SAT EQU  SAT+4
SP2SAT EQU  SAT+8

* Make some common byte values to make adding and subtracting easier
NUM1   BYTE 1         ; Byte value 1
NEG1   BYTE -1        ; Byte value -1

* Boundaries
XMAX   BYTE 230
XMIN   BYTE 8

* Sprite data
P1SP   DATA SP0SAT    ; Sprite 0 used by player 1
P1Y    BYTE 96        ; Player 1 Y (192 / 2)
P1X    BYTE 128       ; Player 1 X (256 / 2)
P1N    BYTE 128       ; Player 1 pattern "name" (character)
P1C    BYTE 1         ; Player 1 color in low 4-bits

.
.
.

*SET SPRITES
      LI   R0,P1SP     * Player 1 SPRITE
      LI   R1,P1Y      * Sprite data order is Y,X,N,C
      LI   R2,4        * 4 bytes for the sprite
      BLWP @VMBW

      LI   R0,SP1SAT   * Sprites 1 to 31 will be disabled
      LI   R1,>D000    * Write >D0 to the Y value of the first unused sprite  
      BLWP @VSBW
.
.
.

RT     
      AB   @NUM1,@P1X    ; Increment Player 1 X
      CB   @P1X,XMAX     ; Range check
      JLE  RTLTX         ; Unsigned Jump if Low or Equal
      MOVB @XMAX,@P1X    ; Clamp X to max boundary
      JMP  RTLTX         ; Jump to update code

LT     
      AB   @NEG1,@P1X    ; Decrement Player 1 X
      CB   @P1X,XMIN     ; Range check
      JHE  RTLTX         ; Unsigned Jump if High or Equal
      MOVB @XMIN,@P1X    ; Clamp X to min boundary

* Right / Left X update
RTLTX
      LI   R0,P1SP+1     ; Address for X data
      MOVB @P1X,R1       ; Put P1X into MSB of R1 for writing
      BLWP @VSBW         ; Write updated X location to VDP
      JMP  LOOP          ; "JUMP" back to loop

 

 

Also, you are setting your work space to 8-bit RAM, and that is bad. You should always load the workspace pointer somewhere in the 256 bytes of 16-bit memory:

 

*LOAD WORKSPACE
MYREG  BSS  >20       <--- reserves 32 bytes which will be in 8-bit memory
START  LWPI MYREG     <--- Sets the workspace pointer to the 8-bit memory address


MYWS   EQU  >8300
.
.
.
START
      LWPI MYWS      <--- Set the workspace pointer to >8300, which is the start of the 256 bytes of 16-bit RAM

 

Also, once you get things working, you might want to have a look at my assembly thread about how to dump the VDP routines for your own faster ones. I hope some of this helps.

 

Matthew

 

 

I wanted to maintain a location and just write the VDP, but I was having trouble with the math function and addressing. I wouldn't normally do it this way it was just the way I thought I could make work and learn from.

 

Yeah, I realize it was 8bit memory but again I wasn't sure where the 16bit memory was so I was just going with the way the examples in the references I was using showed me.

 

Funny you should mention your thread, I have, since posting this read though it once and am reading it a 2nd time. Very good stuff, shame I was working so much and missed all of it when you were writing it up. I'm about to write another AL example and set up the workspace as you suggest. So I'll probably be posting it later as I'm sure to have something I can't resolve. But I am getting better.

 

What would be the best way to write a 16bit value from a reg to the screen? I can think of a way to do it if I now what base it is, ie 10 or 100 or 1000 or 10000 by diving each place by 10 and adding it to the ascii value for 0 then printing that ascii character the the screen. But this seems overly complex.

Link to comment
Share on other sites

I wanted to maintain a location and just write the VDP, but I was having trouble with the math function and addressing. I wouldn't normally do it this way it was just the way I thought I could make work and learn from.

 

When you are learning, you do a lot of things to see what works and what does not, it is part of the process. The hard part is, once you figure things out, not letting some of those hacks become habits.

 

Yeah, I realize it was 8bit memory but again I wasn't sure where the 16bit memory was so I was just going with the way the examples in the references I was using showed me.

 

I did the same thing, since I really didn't know what most of the code was doing. I would get something working, then change parts of it to see what would happen. I wrote a lot of "accidental" code (meaning it was totally by luck and accident that it even worked) when I started out with assembly. Unfortunately I didn't have a resource like A.A. or the Internet, so I was stuck with the E/A manual, the Tombstone City source, and the Lottrup book (which teaches a lot of bad habits, unfortunately.)

 

 

Funny you should mention your thread, I have, since posting this read though it once and am reading it a 2nd time. Very good stuff, shame I was working so much and missed all of it when you were writing it up.

 

The nice thing about forum threads is that you can reply to them months or years later. The content is still valid, so reply and quote parts you have questions about, it is on-going even though I have not added anything to it for a while (been working on the F18A project.) Unfortunately life comes first, until we can figure out a way to make a living with our 99/4A computers. :-)

 

I'm about to write another AL example and set up the workspace as you suggest. So I'll probably be posting it later as I'm sure to have something I can't resolve. But I am getting better.

 

Ask away. The more things you try to figure out, the more you learn. Also, working through something yourself is the best way to learn a problem and understand it completely. Then you can look at how other people solved that same problem (by reading code), and that's where you really make leaps and bounds in your skills.

 

What would be the best way to write a 16bit value from a reg to the screen? I can think of a way to do it if I now what base it is, ie 10 or 100 or 1000 or 10000 by diving each place by 10 and adding it to the ascii value for 0 then printing that ascii character the the screen. But this seems overly complex.

 

If you are talking about keeping a number, like a score, in a 16-bit memory location or register (I recommend a memory location, keep your registers available for doing work, not holding specific values), then there a several options based on a lot of factors. The most direct way is just like you think, you have to keep dividing by 10 to isolate each digit, then adjust that digit for display, which usually means adding 48 to the digit (the ASCII value for the zero character). I have a post about it and code on the CHC site:

 

Interger to ASCII Conversion

 

Matthew

Link to comment
Share on other sites

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

Loading...
  • Recently Browsing   0 members

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