jchase1970 Posted October 28, 2010 Share Posted October 28, 2010 (edited) 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 October 30, 2010 by jchase1970 Quote Link to comment Share on other sites More sharing options...
+adamantyr Posted October 28, 2010 Share Posted October 28, 2010 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 Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 28, 2010 Share Posted October 28, 2010 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 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 28, 2010 Author Share Posted October 28, 2010 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 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 29, 2010 Author Share Posted October 29, 2010 (edited) 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 October 29, 2010 by jchase1970 Quote Link to comment Share on other sites More sharing options...
marc.hull Posted October 29, 2010 Share Posted October 29, 2010 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 ? Quote Link to comment Share on other sites More sharing options...
+adamantyr Posted October 29, 2010 Share Posted October 29, 2010 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 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 29, 2010 Author Share Posted October 29, 2010 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. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 29, 2010 Share Posted October 29, 2010 (edited) 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 October 29, 2010 by matthew180 Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 29, 2010 Share Posted October 29, 2010 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 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 29, 2010 Author Share Posted October 29, 2010 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? Quote Link to comment Share on other sites More sharing options...
+adamantyr Posted October 29, 2010 Share Posted October 29, 2010 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 Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 29, 2010 Share Posted October 29, 2010 (edited) 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 October 29, 2010 by matthew180 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 29, 2010 Author Share Posted October 29, 2010 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 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 30, 2010 Author Share Posted October 30, 2010 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 Quote Link to comment Share on other sites More sharing options...
+adamantyr Posted October 30, 2010 Share Posted October 30, 2010 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 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 30, 2010 Author Share Posted October 30, 2010 (edited) 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 October 30, 2010 by jchase1970 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 30, 2010 Author Share Posted October 30, 2010 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 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted October 30, 2010 Share Posted October 30, 2010 (edited) 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 October 30, 2010 by sometimes99er Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 30, 2010 Author Share Posted October 30, 2010 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. Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 30, 2010 Author Share Posted October 30, 2010 (edited) 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 October 30, 2010 by jchase1970 Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted October 30, 2010 Share Posted October 30, 2010 It's nice to see this much intrest in TMS9900 assembly language Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 30, 2010 Share Posted October 30, 2010 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 Quote Link to comment Share on other sites More sharing options...
jchase1970 Posted October 31, 2010 Author Share Posted October 31, 2010 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. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted October 31, 2010 Share Posted October 31, 2010 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.