Jump to content

adamantyr

+AtariAge Subscriber
  • Posts

    1,891
  • Joined

  • Last visited

Everything posted by adamantyr

  1. Not just a speed freak, but an absolute enemy of the ISR. Perhaps you should break down what the ISR is doing and how to do everything it does without actually using the ROM-based routine? In my CRPG, I keep the BLWP's for my video routines. The main reason I do this is because I don't want the position and counts to be destroyed and have to be restored every time. I could probably write around that, but I want to minimize code space usage. In this instance, BLWP is a minor trade-off of speed for space. I do use direct VDP addressing when I have a serious need for speed, like when I update a portion of the screen that requires it to "jump" addresses rather than just linearly write. (Like when plotting the right-rail statistics and the battle map.) I also pre-process all the display data into a CPU memory buffer prior to writing, so the video routine is not doing any comparison other than loop checks. Adamantyr
  2. Equates aren't opcodes, they're compiler-directives. Essentially, they're symbolic replacements for constant memory values. They make it easy on you, the programmer, to specify a label instead of a raw number that be changed later. You can avoid code replication by storing your addresses in DATA statements, and then using registers pointing to the start of each array to populate your loop registers with an indirect move operation. It means burning up CPU memory, so you'll want to consider if the trade-off is worth it. (It usually is, unless it's a very small amount of data, or a very small amount of loop code.) Adamantyr
  3. I think myself the dragons should consist of at least two sprites of 16x16 pixel size. That lets you get some height on them so they tower over the player. Then you can make them horizontal for "dead" dragons. Adamantyr
  4. Total agreement from me. I got an "Eastern Front: 1941" for the TI in my archives right now. I stopped because I was having problems understanding the AI routine from a top-down perspective, and I also started getting bored with the fact that to make a perfect remake, I had to replicate things I didn't necessarily agree with. Atari Adventure is a classic game, and I'd rather see an inspired-by version for the TI instead of a clone. What I'd like to see myself is a game without a static layout... options like A-Maze-Ing to set the difficulty and characteristics so that each play-through is unique. Adamantyr
  5. Actually, Lottrup relies on the ROM routines as well, the architecture of the Mini-Memory system has them loaded into an area of the 4k ROM. What Matt's talking about is writing your own routines that do everything. The video routines are pretty simple to set up; KSCAN a bit more tricky if you want to not rely on the SCAN routine in the ROM; XMLLNK, DSRLNK and GPLLNK are all very nasty. (I've only done DSRLNK myself, using Travis Watford's version with some modifications.) For my own programming, I still like using BLWP to access them because of the convenience of swapped registers. If I have something that is speed-critical then I just use the direct read/write ports in the base code. That way I get both the convenience and the speed when I need it. Adamantyr
  6. Sure. The idea here is that what the user sees is a finished product before you even touch the VDP port. The only thing you're doing with VDP is direct writes/reads with no logic other than a single loop. For example, your map data does not necessarily need to be one byte per space. You could store the data in only 2-bits (open, wall, corridor, door) and then track actual objects in the dungeon (monsters, treasure, traps) in a separate memory area. This is a way to optimize your data structures; complex objects are kept separate from simple ones, like walls and corridors. So then you have "map processing" going on. You'd extract the map data, and plot this into a display buffer in CPU memory (whatever size on screen, if you used two rows for statistics it would be 32x22 or 704 bytes). The four types would have tile display characters in a small indexed array to use for populating the buffer. Then you'd go back and check each object's position to see if they're within the window's range. If so, then you plot those individually into the buffer. Finally, you actually write the buffer out to VDP at the screen location in one linear swoop. As for checking movement, it's a good idea to pre-load a data array with all the tile types around your player while map processing a new move. That means you can do a single quick check to see if they can move that direction or not. Interaction with objects can be handled in a similar manner, although if doing real-time it may get complicated. (As in, monsters move even if you're not, but that's not technically a Roguelike.) Adamantyr
  7. Don't be afraid to experiment or try things out... just congratulate yourself that you were able to write a working assembly program. One thing you should consider at this stage is that your maps will probably be stored in a CPU buffer. That means any edge checking or object interactions would be done there. The best way to treat the TI display for optimal efficiency is as a pure display port, nothing more. You could do what you normally do in BASIC, using GCHAR, but this is really slow, even in assembly. I suggest you try out for your next assembly experiment the concept of a map in CPU memory, and only displaying a portion of it on screen, and make your "scrolling" map. Adamantyr
  8. Game: Final Fantasy (One, Prime, the Original, etc.) Platform: MSX2, Famicom, Nintendo Entertainment System
  9. One thing, Owen... Roguelike games are categorized as having one particular element... procedurally generated layouts. Using a data map for testing is fine, but you'll also want to investigate random map generation. You can look at Dark Maze to see an example of one at work. It works like this: - Plot a number of chambers on the screen - Each are 3x3 blocks in size of empty space - Store the center location of each into a stack for later calculation - It's okay if they overlap, but they should stay within the boundaries - For each chamber, plot four hallways in all cardinal directions away from the center - If it encounters a boundary, change to a random direction - Periodically, change to another direction - When it encounters an empty space that's not the original chamber, end that direction for that chamber - Random directions should use some intelligence, if it doubles back on itself it will end prematurely Maze generation is actually fun and helps you learn how to craft algorithms. You also start figuring out what all those logic classes are really useful for... for example, with my first version of Dark Maze, the double-back feature meant that it could create chambers that are potentially not connected to others at all. That was a hole in my design I had to fix to make it work properly. Adamantyr
  10. You can use my real name for "Dark Maze". It's in the text file included in the ZIP.
  11. That's too bad. Well, Asgard didn't survive themselves due to bad fiscal management. I recall that Chris Bobbit alienated a lot of the 99'er community as well towards the end. I actually found Donn Granros, the creator of Old Dark Caves and Legends, posting on an artist's forum on the net. Unfortunately he never returned my e-mails. I wondered if he had similar experiences with Asgard. Adamantyr
  12. I don't have access to my TI stuff at the moment, most of it's packed up to move hopefully this weekend... but there is a way to make a program loadable and usable in Extended BASIC that uses character definitions beyond 143. (Which is always the problem with loading large BASIC programs.) Someone gave it to me so I could get a Not-Polyoptics program moved over to disk a few years back. It was a MERGE file that would free up the character spaces and shut off sprites. Adamantyr
  13. Nah. Actually, it's pretty easy, you can't even GET the memory expansion in TI BASIC. And in the old days on hardware, it was possible to write something so long that it was impossible to load it from anything but cassette because it needed the space that the disk drive controller needed to work. Quick way to check available memory in TI Basic, place by itself or at the start of a program: 1 M=M+8 2 GOSUB 1 After it crashes, print M and you know your available memory in bytes.
  14. A hearty congratulations to the winners! A lot of awesome and impressive work from everyone. Now comes the challenging contest... Write a game, still loadable with cassette and no memory expansion (about a 14k limit) in TI BASIC ONLY.
  15. Well, RLE compression may work... I'll explain it for you. All data on the screen is, in fact, a linear array. A full screen is basically 768 bytes of data, from beginning to end, each byte representing a character on screen. All compression algorithms are essentially this: Find patterns to your data that allows you to define the data form in a smaller amount of space. RLE means "Run-length encoding", and it's the simplest and easiest compression format to use. It works very well with a very small set of discrete data patterns (number of unique characters on your map), but breaks down if you have a lot of changes from pattern to pattern. My own maps for my CRPG, for example, are very jumbled with a lot of pattern differences, which makes RLE much less efficient. Let me show you an example, one of your maps converted to raw color for simplicity. Note that with 28x18 characters, it takes up 504 bytes: Okay, now how RLE would break this down is as follows: Gray - 8 Black - 1 Gray - 7 Black - 3 Gray - 11 ... For RLE compression, you can either have a count/character pattern repeated, or you mix data and infrastructure using part of the byte to indicate a count value instead of an actual character. That lets you do singletons, like your keys and swords, without them taking up more dataspace than the actual character does. On this map, doing a rough hand count, there are 178 pattern changes from top to bottom. So if you used a two-byte storage system with a count/byte structure, the map would take up 178x2 or 356 bytes, about a 30% compression rate. There are 63 singletons, so if you did the data/structure embedded format, that would make it 293 bytes, about a 42% compression rate. Note that on the TI disk system, sectors are 256 bytes long. So if you're looking to save disk space, you need to keep things below/above 256 byte increments. So for this map, either method takes up the same disk space. The main problem with RLE is it works great when you have maps that have a lot of identical patterns running horizontally... do a map with a vertical style and suddenly it doesn't compress nearly so well. An area with a lot of singletons would also be a problem; the data embedded form at least guarantees that your map never takes up MORE space than uncompressed. Also, the time to decode the map from RLE would be some work... you could nearly use HCHAR to build the screen for you except that it self-corrects to the same ROW when over-flowing. Adamantyr
  16. Yeah, doesn't help I'm kind of sporadic on updates either. I just posted a new blog entry today on attack pattern mapping. Adamantyr
  17. Long way to the demo, alas... I'll post another video when I got something interesting going on. Since I'm saving special effects (actual animation in combat) for later, it will be a bit. Adamantyr
  18. Sorry Tursi, but you're wrong. When I had it set to DISPLAY mode, it would only print the first 28 characters to the file from each row string. My display program kept failing with BAD VALUE because the SEG$ was trying to access a location that wasn't possible. After I changed it to INTERNAL it started printing the entire string as intended. Adamantyr
  19. Yeah, INTERNAL is the best option for what you're doing. I tried using DISPLAY, but it auto-truncates to 28 characters in BASIC. And it won't permit characters above 127 either, I think. If you do a hex-edit on the binary file created, you'll note that each line is actually 34 characters or bytes. That's because the internal format is using a two-byte header on each line. It's been awhile since I worked with files in BASIC, but I think one is a length byte and the other is a type byte. (numeric or string) It could be worse; numeric variables in BASIC are always Radix 100 floating point numbers, so they take up 8 bytes apiece. If I was going to revise TI BASIC at all, I'd add an integer type so you could ditch FP entirely. (Writing all the type-casting tools would be a pain, though.) In assembly, you have absolute control. Using FIXED determines record size, so you just put what you want into a buffer in VDP and write it out or read it in. That makes it much more efficient, since you can define your own file data structures. The memory-image of the screen is really simple, just a straight 768 bytes that's dropped right into the screen memory. Adamantyr
  20. Yeah, the file isn't getting created right by the look of it... I'm investigating. I haven't done BASIC files in a long time... Assembly is SO MUCH BETTER. SOLUTION: Move the C$="" to BEFORE the C loop starts. Always the easy ones. Also, remove the FIXED 32 keywords from the the OPEN statements in both programs. (Put INTERNAL back in if you haven't done so already) Adamantyr
  21. Well, first of all, there should be NO data statements at all in that second program. One program reads those DATA statements from Magellan and creates the file. The second actually reads the file and prints it out. If you're trying to do it all in one program listing, I think you got the wrong idea. Adamantyr
  22. It's not a data problem, READ R$ should be INPUT #1:R$. My bad. Adamantyr
  23. Colors are 0-15 in assembly, 1-16 in BASIC, the usual "offset by one" bug. What's your exact goal with this small program? Just to display your screens? If so, speed shouldn't be a problem. If you want to read those DATA statements in and then output that data as a string-readable file for your eventual game, this should do the trick: 100 OPEN #1:"DSK1.MF1",OUTPUT,INTERNAL,FIXED 32 110 RESTORE 9190 :: FOR R=1 TO 24 :: FOR C=1 TO 32 :: C$="" 120 READ CHA :: C$=C$&CHR$(CHA):: NEXT C 130 PRINT #1:C$ :: NEXT R :: CLOSE #1 ... 9190 {Data here} Then you can read them back in and display them as follows: 100 FOR S=1 TO 14 :: READ F,B :: CALL COLOR(S,F,B) :: NEXT S 110 CALL CHAR(96,"11FF444444FF1111") :: CALL CHAR(104,"001F356AFEB686FC") :: CALL CHAR(112,"00BDFF3C191A3C7E") 120 CALL CHAR(113,"3C66A5A5BDBDA5FF") :: CALL CHAR(120,"0000E0A0BFA5E501817E247EA5244200") :: CALL CHAR(128,"0102044830304880") 130 CALL CHAR(128,"0102044830304880") 140 CALL CLEAR :: CALL SCREEN(2) 150 OPEN #1:"DSK1.MF1",INPUT,INTERNAL,FIXED 32 160 FOR R=1 TO 24 :: INPUT #1:R$ :: CALL HCHAR(R,1,ASC(SEG$(R$,1,1))):: CALL HCHAR(R,2,ASC(SEG$(R$,2,1))) 170 DISPLAY AT(R,1):SEG$(R$,3,28):: CALL HCHAR(R,31,ASC(SEG$(R$,31,1))):: CALL HCHAR(R,32,ASC(SEG$(R$,32,1))) 180 NEXT R :: CLOSE #1 190 GOTO 190 1000 DATA 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,15,1,11,1,7,1,16,1,8,1,2,1 As you can see, I used HCHAR to populate the four columns ignored by DISPLAY AT. It's a bit hacky, but you could replace this with an assembly-linked routine that would be better later. Adamantyr
  24. Fixes: - DISPLAY AT only works on columns 3-30, it was adapted from the PRINT statement which only works with those columns because old TV screens tended to cut them off. Use HCHAR(ROW,COLUMN,CHA) instead - You don't need the second IF at the end of line 110, just IF COLUMN > 32 THEN COLUMN=1 :: ROW=ROW+1 - In fact, you don't need to use IF's at all, just do a loop, you have a finite known value for how many columns and rows you are filling So try this code instead: 100 CALL CLEAR :: CALL SCREEN(4):: RESTORE 230 105 FOR R=1 TO 24 :: FOR C=1 TO 32 110 READ CHA :: CALL HCHAR(R,C,CHA) :: NEXT C :: NEXT R 120 GOTO 120 This is going to be INCREDIBLY SLOW, by the way, but DISPLAY AT is no faster. Unless you write an assembly routine, it will always be that way. The most effective way to store data screens in BASIC alone is to use a string array to store rows, and use DISPLAY AT to display rows after they're loaded from disk. This does have the 28-column limitation, though. Adamantyr
  25. Erg... the problem here is that BASIC's data structures and the screen are aligned in just the right way to totally ruin your day. Specifically, strings, the ideal data storage method, can only be a maximum of 255 bytes. (A length byte is at the start of a 256 byte block.) So you would need three strings to represent the data on a full-size screen. Which means your assembly routine either has to process row strings one at a time (which means the display is severely retarded in efficiency since it has to return to BASIC for each row) or accept three or four strings as parameter data. Here's a better idea: How many unique screens do you have? If the count is reasonable (20 or so), you could store them as "program" files, also known as memory-images. I do this myself for various screens in my CRPG. Each screen fits in exactly 4 sectors (1 sector for the record, 3 for the data) and occupies exactly 1K on a disk. The only serious limitation here is that the TI file system only permits 127 files maximum on a single disk. Using this method though, and an assembly program that only takes a single parameter (string for the file name or file path) that just reads it DIRECTLY into the VDP screen memory, bam, instant screen change. Plus you can change your data structure in BASIC to just have a file name for the individual map, instead of hard data, which gives you more room for other stuff. One caveat: The character sets in BASIC are a little whacked. The character set is all offset by 96 because the lower part of the character definition table is used for other purposes. This is why you can't have characters defined past 159 in BASIC (and 143 in Extended BASIC); you're literally AT the end of the table already. And in Extended BASIC, 144-159 are used for the sprite attribute table. Adamantyr
×
×
  • Create New...