Jump to content

Photo

Assembly BYTE and more questions


64 replies to this topic

#1 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • 340 posts
  • Location:Newburgh IN

Posted Thu Oct 28, 2010 1:31 PM

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, Fri Oct 29, 2010 9:21 PM.


#2 adamantyr OFFLINE  

adamantyr

    Dragonstomper

  • 577 posts

Posted Thu Oct 28, 2010 2:22 PM

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

#3 matthew180 OFFLINE  

matthew180

    Stargunner

  • 1,827 posts
  • Location:Burbank, California

Posted Thu Oct 28, 2010 2:27 PM

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

#4 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Thu Oct 28, 2010 3:21 PM

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

#5 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Fri Oct 29, 2010 10:40 AM

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,

[codebox]
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
[/codebox]

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, Fri Oct 29, 2010 10:54 AM.


#6 marc.hull ONLINE  

marc.hull

    Dragonstomper

  • 942 posts
  • Location:Oklahoma CIty.

Posted Fri Oct 29, 2010 11:07 AM

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    @LOOPP1      LI R1,RT        JMP @PRINTP2      LI R1,LT        JMP @PRINTPRINT   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 ?

#7 adamantyr OFFLINE  

adamantyr

    Dragonstomper

  • 577 posts

Posted Fri Oct 29, 2010 11:09 AM

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    @LOOPP1      LI R1,RT        JMP @PRINTP2      LI R1,LT        JMP @PRINTPRINT   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

#8 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Fri Oct 29, 2010 12:22 PM

Well, I did this
[codebox]
LI R0,>01E2 *set sprites to double size
BLWP @VWTR
MOV R0,@>83D4
[/codebox]
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.

#9 matthew180 OFFLINE  

matthew180

    Stargunner

  • 1,827 posts
  • Location:Burbank, California

Posted Fri Oct 29, 2010 12:59 PM

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, Fri Oct 29, 2010 1:01 PM.


#10 matthew180 OFFLINE  

matthew180

    Stargunner

  • 1,827 posts
  • Location:Burbank, California

Posted Fri Oct 29, 2010 1:14 PM

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

#11 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Fri Oct 29, 2010 1:16 PM

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

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?

#12 adamantyr OFFLINE  

adamantyr

    Dragonstomper

  • 577 posts

Posted Fri Oct 29, 2010 1:24 PM

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

#13 matthew180 OFFLINE  

matthew180

    Stargunner

  • 1,827 posts
  • Location:Burbank, California

Posted Fri Oct 29, 2010 1:38 PM

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, Fri Oct 29, 2010 1:43 PM.


#14 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Fri Oct 29, 2010 2:35 PM

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

#15 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Fri Oct 29, 2010 9:42 PM

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

#16 adamantyr OFFLINE  

adamantyr

    Dragonstomper

  • 577 posts

Posted Fri Oct 29, 2010 10:07 PM

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

#17 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Sat Oct 30, 2010 9:37 AM

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.

[codebox]
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
[/codebox]

Edited by jchase1970, Sat Oct 30, 2010 9:41 AM.


#18 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Sat Oct 30, 2010 9:56 AM

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.

[codebox]
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
[/codebox]

#19 sometimes99er OFFLINE  

sometimes99er

    River Patroller

  • 2,786 posts
  • Location:Denmark

Posted Sat Oct 30, 2010 10:00 AM

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, Sat Oct 30, 2010 10:09 AM.


#20 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Sat Oct 30, 2010 10:41 AM

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.

#21 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Sat Oct 30, 2010 10:50 AM

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

[codebox]
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

[/codebox]

Edited by jchase1970, Sat Oct 30, 2010 10:51 AM.


#22 retroclouds OFFLINE  

retroclouds

    Stargunner

  • 1,370 posts
  • Location:Germany

Posted Sat Oct 30, 2010 11:52 AM

It's nice to see this much intrest in TMS9900 assembly language :cool:

#23 matthew180 OFFLINE  

matthew180

    Stargunner

  • 1,827 posts
  • Location:Burbank, California

Posted Sat Oct 30, 2010 5:43 PM

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

#24 jchase1970 OFFLINE  

jchase1970

    Moonsweeper

  • Topic Starter
  • 340 posts
  • Location:Newburgh IN

Posted Sat Oct 30, 2010 6:26 PM

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.

#25 matthew180 OFFLINE  

matthew180

    Stargunner

  • 1,827 posts
  • Location:Burbank, California

Posted Sat Oct 30, 2010 7:14 PM

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




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users