Jump to content

adamantyr

+AtariAge Subscriber
  • Content Count

    1,852
  • Joined

  • Last visited

Posts posted by adamantyr


  1. For border checking, a 2-coordinate system is best.

     

    I've tried out the idea of a single index value tracking on a 2-axis data set... it's possible to do, but not really worth the effort because of the math involved.

     

    Adamantyr


  2. Contest guidelines:

     

    *Write a TI console BASIC game

    *Game must be <=14k (for cassette loading)

    *All entries due by January 14th

    *You may enter as many 14k games as you wish, but only one will be considered for prizes

    *Game may be either an original idea or a port of another game for another platform

    Good initiative.

     

    How do one measure that a game is <= 14K ?

     

    :)

     

    If you get "MEMORY FULL" you've gone too far. :)

     

    An old cheat method to determine available space in BASIC is to insert this at the start of the program:

     

    1 A=A+8
    2 GOSUB 1
    

     

    When the program crashes with "MEMORY FULL", print the A value. That's your available memory.

     

    Adamantyr


  3. I see a few things... your delay was in the wrong place, it should be AFTER you have written the character, not before.

     

    I also made some changes to how the joystick is scanned. Since the X and Y values are in a single word, you can easily check for no activity and just loop back.

     

    Code below

     

     

     

    *
    * Owen Brand, Nov 13, 2010
    *
    * Clear the screen.
    * Assumes the default graphics mode I.
    *
          DEF  START
          REF  VSBW,VWTR,VMBW,KSCAN
          AORG >A000                      * Start program at bottom of high memory
    CTAB   EQU  >0380                      * equate location of colorset table in RAM
    
    * Data constants
    B4     BYTE 4
    BN4    BYTE >FC
    
    * The linker will branch to this location
    * to start our program.
    START  
          LI   R0,CTAB                    * table location
          LI   R1,CSET                    * definitions
          LI   R2,32                      * number of bytes to write
          BLWP @VMBW
    
    *      Interrupts need to be disabled any time the VDP
    *      is being accessed.
          LIMI 0
    
    *      Always know where your workspace is!
          LWPI >8300
    
    
    *      Set the background color to white >F
    *      VDP register 7 controls the text mode
    *      text color and the background color for
    *      the other modes.  All other VDP registers
    *      are assumed to have set graphics mode 1.
    
          LI   R0,>071F                   * Register 7, black on white
          BLWP @VWTR                      * Write the register
    
    
    *      Set up to clear the screen.  Assumes the
    *      Name Table is set to address >0000 in VRAM.
    *      All the names (tile / character values) in
    *      the Name Table will be set to the space character
    *      which is, well, a space, so it has no foreground
    *      bits, so the screen will show only the background
    *      color.
    *
    *      Note, only the HIGH BYTE is transfered to the VDP
    *      hence using >2000 loads 32 (>20) into the MSB of R1.
    
          CLR  R0                         * Start at >0000 in VRAM.
          LI   R1,>2000                   * Write 32 (space char)
          LI   R2,768                     * 32x24 tiles = 768 total to write
    
    LOOP   BLWP @VSBW                      * Write the byte
          INC  R0                         * Next VRAM screen location
          DEC  R2                         * Count the byte just written
          JNE  LOOP                       * If not done, write again
    
    *      The DEC instruction compares the result of the decrement to
    *      zero automatically (as do many instructions), so the JNE is
    *      really saying "jump if R2 is not zero".
    *      This will place a "@" at screen location 110
    
          LI   R0,110                     *Screen location in VDP RAM
          LI   R1,>4000                   * ASCII code for "@"
          BLWP @VSBW                      * Write it
    
    JOYCK  LI   R1,>0100                   *check for joystick 1 input
          MOVB R1,@>8374                  *check for Y return
    LP     LIMI 2
          LIMI 0
          BLWP @KSCAN                     *check for input
          MOV  @>8376,R1                  * Move joystick XY values into R1
          JEQ  LP                         * If 0 (no movement, jump back to KSCAN
          CB   R1,@B4                     *is the Y value "4"? (up)
          JNE  T1                         *if not, go to the next comparison
          LI   R1,>2000
          BLWP @VSBW
          AI   R0,-32
          JMP  PRINT
    T1     CB   R1,@BN4                    *compares MSB of R1 to >FC (down)
          JNE  T2                         *if not, go to the next comparison
          LI   R1,>2000
          BLWP @VSBW
          AI   R0,32
          JMP  PRINT
    T2     SWPB R1                         * Swap bytes in R1 for Y comparisons
          CB   R1,@B4                     *is the X value "4"? (right)
          JNE  T3                         *if not, go to the next comparison
          LI   R1,>2000
          BLWP @VSBW
          INC  R0
          JMP  PRINT
    T3     LI   R1,>2000
          BLWP @VSBW
          DEC  R0
    PRINT  LI   R1,>4000                   *load the ASCII character to print
          BLWP @VSBW                      *print it
          LI   R4,3000                    *Start the delay loop
          DEC  R4                         *decrement register 4 (part of delay)
          JNE  $-2                        *jump back one word in memory to DEC
          JMP  LP                         *back to KSCAN routine
             
    CSET   BYTE >10,>10,>10,>10            
          BYTE >10,>10,>10,>10            *set "@" to "red"
          BYTE >C0,>10,>10,>10            
          BYTE >10,>10,>10,>10            
          BYTE >10,>10,>10,>10 
          BYTE >10,>10,>10,>10
          BYTE >10,>10,>10,>10
          BYTE >10,>10,>10,>10
          END  START
    

     

     

     

    Adamantyr


  4. Looking good, Owen! Just set yourself small goals and achieve them one by one. Doing borders and being able to detect and pick up objects on the screen is a good set of goals.

     

    I agree with Vorticon about the VDP utilities... I've butted heads with Matthew on this subject before. :) I'd call writing your own VDP utilities and VDP read/write techniques an optimization step, and probably best for the intermediate programmer who has mastered the basics (replicated everything he could do in BASIC and Extended BASIC) and is ready to move on into what assembly can do for you that can't be done elsewhere.

     

    One area that is a must for assembly programming is understanding boolean logic. (AND, OR, NOT, bit masks, etc.) TI BASIC and Extended BASIC use these, but you can use IF/THEN without ever really understanding what's going on under the hood. I had a college course on the subject in my CS path, can anyone recommend a decent book that's good for a beginner here?

     

    Adamantyr


  5. That works... Thanks sometimes!! made it green, though--- instead of red. =) I need to understand why we changed the 9th BYTE in that chain and not the 5th and why "C" didn't give me light red.

     

    0 = 1st byte

    .

    .

    .

    8 = 9th byte

     

    Like I said, 0 as a legit value, kinda hard to wrap your head around. :)

     

    As for the color being off, the colors are off by 1 compared to BASIC. As follows:

     

    >0 - Transparent

    >1 - Black

    >2 - Medium Green

    >3 - Light Green

    >4 - Dark Blue

    >5 - Light Blue

    >6 - Dark Red

    >7 - Cyan

    >8 - Medium Red

    >9 - Light Red

    >A - Light Yellow

    >B - Dark Yellow

    >C - Dark Green

    >D - Magenta

    >E - Gray

    >F - White

     

    Adamantyr


  6. Interesting... The "@" is in set #5. I assumed that changing the fifth BYTE would set it properly. Maybe I'm mixing up XB and assembly sets...

     

    Yeah, BASIC doesn't have the entire set available, so they offset the values to make it clean. Just like how the colors are all incremented by 1 so there is no "0" value.

     

    Fortunately the ASCII values are still intact. So if you need to know the byte to use, just divide the ASCII value by 8, drop the remainder, and that's your byte to change. An '@' is ASCII 64, so the color byte to adjust is the 8th.

     

    In assembly, you run into base 0 computations everywhere. That means that a value of 0 is "the first position". The best way to wrap your head around this it to think about it as an offset from a base address. Non-programmers probably have trouble from the get-go with the idea of 0 not meaning "nothing" but is treated as a legitimate value.

     

    Adamantyr


  7. Excellent points, Matthew!

     

    I also started programming when I was around 10 years old. And frankly, I had NO clue what I was doing. I read the BASIC learning book, and studied programs, but so much of it was weird and incomprehensible for years. There was an actual solid computer class at my junior high school that may have helped, but the teacher retired the year before I could go to it and the new teacher eliminated all the programming classes from the curriculum. So I was stuck reading my books and trying to figure it out. Lottrup's book just made things worse, because frankly, the Mini-Memory assembler is a TERRIBLE platform to develop on... it works, but that's about the most you can say about it.

     

    I remember the first time I realized I could use strings to store numeric data. What I actually did was store letters, like A, B, ect, and use those as codes for items and mapping. And boy was I ever excited about it! I wrote some Zelda-esque game with it, which sadly I can't seem to find now... I tried writing a LOS algorithm by hand, but in Extended BASIC it was way too slow... my theory was I could use the SIN and COS functions to plot out from the center of the display to the edge, and just do a 360 degree sweep around to determine tile blockage. I think I got bored watching it after about 10 minutes and realized it wasn't a tenable way to do it.

     

    I had similar assembly disasters to Matt's, misinterpreting what commands did, confusing them with BASIC-like commands. I laugh at it now, because I hadn't realized that the source code for a complete game (Tombstone City) was on the second E/A disk. It probably wouldn't have helped a lot to study it, but who knows... Even after I picked back up TI programming after my return to college 8 years ago, I still had to do some studying with an older eye to figure out how the OS was structured. I actually had set out to write Ultima II on the TI, I had planned to store and dynamically load the tile graphics using a complicated queue system into a full-bitmap mode design. Not really a great way to use memory or cycles... better to write programs that take advantage of the native design, not try and force another on it.

     

    I know how you feel with the frustration. I've felt that so many times... heck, I'm feeling that now. I'm at a pretty heavy "lots of work, not a lot of return" stage with my CRPG engine, and I'm finding Minecraft, Avernum 3, and other games an easy distraction. We do hobby programming for fun, after all... when it's not fun, it's easy to fall off the track.

     

    But don't give up on your games! Think about the 10-line contest. You had no problem finishing things there, right? The trick is scale. You need to build some smaller programs to test out what you want to do with the big projects. Spend a little time just experimenting. Share your code efforts here on the forums, we'll be happy to offer advice and praise when you need it.

     

    Adamantyr


  8. Adam--- as soon as the crap game contest is over, we're going to do a 12k or under TI console BASIC only contest (so it will fit on cassette). :)

     

    The goal? A cassette compendium, of course!!! :)

     

    Oi, you can go up to 14k on a cassette! :)

     

    Adamantyr


  9. I agree with the masses... an awards system can easily become a game of favorites and cliche's.

     

    We've got a great friendly atmosphere here with the contests system, let's keep going with that. (Although I must admit I'm not really fond of the "crap game" contest myself... I'd rather do something like "only in BASIC")

     

    Adamantyr


  10. Here is a bigger example with a source value that does not fit in a single 16-bit value.

     

    DIVIDE DATA 1234       Divisor must be a 16-bit value
    .
    .
    .
           LI   R8,>000F     Load 32-bit dividend with >000FFFFF
           LI   R9,>FFFF
           DIV  @DIVIDE,R8   Divide: 1,048,575 / 1,234 = 849 remainder 909
    

     

    After the DIV, R8 would contain 849 and R9 would contain 909.

     

    One other point, DIV and MPY are both unsigned operations. Signed operations require a bit of extra work; you'll have to store the sign bits for divisor and dividend and restore the true value after completing operations.

     

    Curiously, the only two new opcodes added in the TMS9995 processor were signed multiply and divide operators.

     

    Adamantyr


  11. So if I use an equate....

    CHRPT EQU >0800
    

     

    Then that places my PDT at that specific location... See, another example of this book confusing the hell out of me... All the tables and such are at hard locations in this book....

     

    I think I see part of your problem here...

     

    The EQU label is not saying "Put the character pattern table here" or "the character pattern table is here". It is literally just saying "this label points to this address".

     

    It is used by the compiler and the programmer to replace something that would ordinarily be a number with a label so that, if you decide you want to move it to another location later, you can just change a single label and have it change everywhere.

     

    So what does determine the character pattern table location? The settings in the VDP registers. And they have default settings coming from the E/A cartridge as follows:

     

    R1=E0 Standard mode

    R2=00 Screen image at >0000

    R3=0E Color table at >0380

    R4=01 Char pattern table at >0800

    R5=06 Sprite attribute table at >0300

    R6=00 Sprite pattern table at >0000 (not the same as char pats!)

    R7=F5 White on blue

     

    Does that help you grok this a bit better?

     

    Adamantyr


  12. I am writing just an assembly routine. EA3. It's just all the figuring of where the data needs to go, offsets, buffers, bytes words.... It's the whole concept. I understand WHY it all works and even HOW it works.... It's the execution of it that makes my eyes bleed. I've never thought this way... I've only ever coded in BASIC languages, TI and bAtari. I wish it were intuitive to me, as it seems to be for so many of my colleagues here. I'll keep reading and trying. Nothing to it but to do it, right?

     

    It isn't an easy transition from an imperative language like BASIC, I'll agree. I didn't quite grasp it myself as a teen either. I kept thinking "What's the command to do this?" It wasn't until I was back in college years later that I had my "Eureka!" moment.

     

    Maybe the best way to try and approach it is to think of the command in BASIC/extended BASIC you want to use, and then ask yourself "Now how would that command actually work? What would it actually do in assembly?" Start with something simple, CALL COLOR.

     

    Adamantyr


  13. Point well taken on the string usage... I'm wondering there'll be a price to pay in speed though. I don't want to get so spoiled by the overdrive mode in Classic99 that I make the game unbearably slow on a real machine.

     

    Numeric variables are just as slow, most of the time, since everything is pushed through the ROM and GROM floating-point routines.

     

    Adamantyr


  14. Ugh... man, I tell ya... As much as I try--- as many times as I've tried to write in assembly, it still just makes my brain explode. I've been sitting here staring at this book and trying a hundred different things and it's just not happening. I'm trying to work on a little something for Keith and his Dead Station game, but it's frustrating beyond description. It's such a simple thought... redefine ONE character, change ONE character set color, draw the 768 bytes I have already onto the screen. Drawing is easy.

     

    DEF START
    REF VMBW
    START
    
    LI 	R0,0
    LI 	R1,MD0
    LI 	R2,768
    BLWP   @VMBW
    LP LIMI   2
    JMP	LP
    

     

    Tables just confuse me. I don't know...

     

    Think of it like this... the VDP is just data storage. There's nothing there BUT data. All you need to know is where to find it, and what order it's in.

     

    Also, doing BASIC/Assembly cross-over work is seriously brain-hemorrhaging hard stuff. I tried to do it myself back in my teens, and couldn't grok it at all. I wondered how on earth anyone learned assembly programming that way.

     

    Adamantyr


  15. This might be a dumb question... more often than not the Lottrup book (while brilliant) confuses the shit out of me unnecessarily.

     

    The character table... assuming I want to change the definition of character 128 or character >80, is there a simple way to determine how to address that particular 8 byte chunk? A reference for each location? For instance, according to the Lottrup book, character #35 starts at >0918, increasing by 8 bytes for each character definition. If I wish to redefine character 128, I take >0918 and add 93*8 to it? Is this correct?

     

    Or am I totally missing the point.....

     

    This is very much an issue of me thinking in dec and not hex

     

    Yes, that is correct. A better way to think of it is like this:

     

    Address of character = Starting address + ( character value * 8 )

     

    In assembly, you can do this by having an equated label to the address. A code snippet is below:

     

    CHRPAT EQU  >0800
    .
    .
    .
    * Read a character pattern into BUFFER, @CHAR contains character to read
          LI   R0,CHRPAT
          MOV  @CHAR,R1
          SLA  R1,3
          A    R1,R0
          LI   R1,BUFFER
          LI   R2,8
          BLWP @VMBR
    

     

    Does that clear it up?

     

    Adamantyr


  16. Any thoughts on whether I should stop now and go to a text-string-based system for storing that information, or forge ahead with my DIM'd array?

     

    Numeric variable = 8 bytes

    String variable = 1 byte per character

     

    Strings are much better. It does add an additional operation to convert a string back into a numeric value, but the trade-off is worth it. Plus, you have 11k of stack that you can't use for program space.

     

    One question I had was, how are you maintaining different maps for each player?

     

    Adamantyr


  17. If you could point me in the direction of where that's been discussed before (because I feel like I've seen it), or break it down quickly for me, I'd appreciate it. My plan for loading game maps in was to allow a map editor and user-customizable maps, and also to retain a "space station" feel. The game could just as easily be played on a totally random board, at least if I include some of the features I'm considering (a laser to blast out wall pieces, for example, which would eliminate the need for clear paths). But a totally jumbled, random map wouldn't look very "space-stationy."

     

    I think it was in the Beryl thread that I laid it out... I'll do it again here:

     

    * Start with a blank map of nothing but walls

    * Plot random chambers on the map

    o You can either make them fixed sizes or slightly random in height/width

    o Overlapping is okay if you don't mind that, but it can make oddball shaped chambers

     

    * From each chamber, plot a corridor from the center

    o Plot anywhere from 1-4 cardinal directions from the center

    o Don't start plotting until you hit the edge

    o If a border is reached, change direction

    o You'll need some logic for direction random changes, otherwise you may just backtrack on your path and end early

    o If another empty chamber or corridor is struck, end the plotting for that direction

     

    * Populate items, monsters, etc. in the maze, either totally random or use the center coordinates of chambers as guides

     

    For a space station, you may want a more rigid system that makes logical sense. A space station would likely have single narrow corridors connecting larger rooms, and not a lot of overlap. Or, you may also want the rooms to have a more logical order. A main "central" room that is connected to all other rooms. The secondary rooms aren't necessarily connected to one another.

     

    Also, why not have pressure locks on each room exit that have to be hacked open? If you have a "room" generation system, you can do some interesting things as well. You have "rad levels" per room so some rooms have high radioactivity.

     

    Adamantyr


  18. Sweet! Can't wait to see more.

     

    So you're loading static maps from disk? Have you considered doing procedural generation? If you use a random seed value system, you could actually get a static set of maps that way.

     

    Adamantyr


  19. 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


  20. We got our TI-99/4a in 1984, for my brother's 12th birthday. My mom and dad had decided a computer would be a good thing to have, and Texas Instruments already had an impressive line with the Speak n' Math and Speak n' Spell units. Plus, the price was right at $249.99 with a $100 instant rebate at Jafco. (Jafco being a Sears-like store that operated in the Pacific Northwest. They later changed their name to "Best", before disappearing entirely. NOT related to Best Buy. My TI box still has Jafco stickers on it.) My parents were unaware that TI had just discontinued the product line, of course... And to be honest, most other computers were way too expensive for your average lower-middle class family in that era. Paying $800-1000 was just unthinkable for what was widely considered a "toy".

     

    My brother was told he could pick the game cartridges he wanted from what was available. What caught his eye (being into D&D) was the Tunnels of Doom box, with the blue cover featuring a dragon breathing fire on a figure with sword and shield. It was $59.99, though, compared to the $29.99 price tags on other games, so he had to give up two picks to get it. We also got A-Maze-ing, Munchman, Parsec, and Alpiner on that first trip, I believe. I know we eventually got enough cartridge UPC's to send in for the free speech synthesizer, but we didn't have one initially.

     

    All the games were very enjoyable, but Tunnels of Doom was a world apart. We did Pennies & Prizes many times at first, before my dad started "Quest of the King". I remember the first game was very chaotic... Mauve kept dying at fountains and eventually everyone died to a random encounter on the 2nd level. Since there was three of us, we traded off with each character deciding our actions independently. I think that was really a good way to play a party-based CRPG, but it eventually morphed into MMO's.

     

    We got a Triton Catalog at some point... I still have every issue except the very first one from late 1983. I'm not sure how we came into it, but it was a definite life-line for the system, because Sears, Payless and other stores soon after stopped carrying software. (It wasn't just TI getting phased out, though, nearly every computer got boned in the post Video Game Crash.) My brother lost interest in the system because a friend of his had a TRS-80 Color Computer and had an impressive set of magazines and games for it. Plus, Radio Shack was still around and easy to get everything you wanted at, so he ended up moving on to the CoCo and left the TI behind for me. (Years later, at the Tacoma TI faire, he bought a whole new TI system (with disk drive, PE box, the works) because he wanted the spreadsheet software. He had been frustrated by the lack of good utility software on the CoCo.)

     

    We actually found a computer store (Northwest Computers) in Mount Vernon, WA, that sold TI equipment. The owner was a 99'er, although he sold other vintage computer software and hardware. I bought my PE box through him in 1987, pooling birthday money from several sources to do so. It was great to have an actual disk system at last, I had been getting really tired of cassette tapes at that point. :) Plus, a good friend of mine also owned a TI and we both traded off games with one another from time to time. He also gave me the TexComp catalog, which offered a whole new set of things to order. (I just ran into this old friend at Microsoft, and in my building no less. Most of his TI stuff was lost, though, when his parents passed away, and the awesome XB game "Food Frenzy" he had been working on has been lost to the ages. Alas.) I visited Bits N' Chips in Lynnwood, WA, once around 1988, and actually got copies of several games on disk, including Legends. (I later realized I was essentially paying a buck a disk to pirate software.) I got a subscription to Micropendium around 1990 as well.

     

    I really wanted to program great things in my youth. I worked very hard to learn how to program in BASIC and Extended BASIC. Unfortunately, assembly was nearly incomprehensible to me. I didn't have the necessary background to understand why things worked like they did, and the few clumsy attempts I did to create a simple program failed, and I had no idea why. Truthfully, looking back... I probably wouldn't have gotten far. The speed of compilation is so slow on the TI, and without a debugger, you'd be tearing your hair out trying to find problems. Plus, I'm pretty certain I'd have burned out my disk drives with all the compiling eventually.

     

    I do need to dig up some of my old Extended BASIC projects, dust them off, maybe put them up on Walid's site.

     

    Adamantyr


  21.        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


  22. 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

×
×
  • Create New...