Jump to content

adamantyr

+AtariAge Subscriber
  • Posts

    1,891
  • Joined

  • Last visited

Everything posted by adamantyr

  1. Tunnels of Doom is the heaviest of the bunch, it has five 6k GROM chips for a total of 30k of data. Seriously big at the time. Adamantyr
  2. It's a matter of what you're focusing on, I think, coding or game design. In my mind, the target audience is someone who's done a lot of game programming in TI Basic and TI Extended Basic and wants to try out assembly. So their main goal is to be able to do everything they could do IN Basic. I'd focus on using the Editor/Assembler as the chief platform, and NOT doing Basic/Assembly cross-over. I have heard that many 99'ers learned assembly this way, but my experience with it was it was a very advanced topic and not suitable as a starting point. As an example, a TI Basic programmer would want to know how to do random numbers. They've had this ability easily through the RND value. A tutorial of dry pseudo-random theory and implementation is interesting to someone wanting to write a better random number generator, but just confusing and scary to this audience. "I just want random numbers!" They will cry. So it's better to give a short explanation that random numbers are not really random, a simple routine that just does a base add on a stored memory value, explain how it works, then how to make it a bit better. That's also how a lot of game designers are as well. Their head is in the clouds on what they want to accomplish in the game. HOW they do it in code isn't always as interesting or relevant. You can always go back and re-engineer a routine to be more optimal, more efficient, and more clever. I'd definitely devote a chapter or even a third of the book to "game design", because a lot of it is way beyond just knowing how to code. Adamantyr
  3. Funny, I was just thinking it would be neat to write an actual "Guide to Writing Games in Assembly Language on the TI-99/4a". Maybe even give it a mock-up Compute! cover. Adamantyr
  4. Whatever method you use, you'll only be loading part of the map into memory at any given time. That's the only way you can have such a large map. I tried this method with my own CRPG, having a "big world map" that reloaded new sections every time you approached a boundary, but the effect was a lot of stops every 8 or so paces in a given direction. The main issue was a single record access had to be made for every row. The TI disk system is pretty fast, but this adds up, especially when it's the user moving the screen and they definitely notice a second or two of delay. I noticed that this issue exists in Ultima IV on a lot of 8-bit systems; it's actually a rather slow and cumbersome game to play on these platforms as a result. If you go with sections, you can greatly minimize this issue. This is what I did with my CRPG; I just have a 4k buffer and a map header record that records height and width. That way I can have maps that are 64x64, 128x32, 32x32, or any size I want. The only reloads occur when you actually exit the map. Adamantyr
  5. Hah, I got an Asgard Extended Basic 3 Super-cart! Only six of them made, by rumor. Beat that! Adamantyr
  6. *Ahem* Er, April Fools? Truthfully, it's totally possible to adapt the game to the TI-99/4a platform. I actually started doing just that 6-7 years ago when I took my TI out of mothballs while going to school. However, there's some considerable hurdles to jump over for the display: - How to do the 3D? The TI doesn't have point/line style graphics except in the extremely expensive bitmap mode. Character graphics can be used, but it's a whole new system... and everybody HATED the 3D dungeons anyway - Ultima II has 64 unique tiles. Attempting to define all of these as 16x16 size tiles would burn every single character available, and leave nothing for letters, numbers, or even a space! Some recycling can cut down tile usage a bit - You'd end up doing a lot of VDP writes every time the character moved if you wanted "rotating" assignments, and you'd have to maintain a tile buffer/assignment system for each pass - It's possible to use some kind of data structure that does a minimal of tile updates per pass. If a grass tile is already there, it won't redefine it, for example. Still a LOT of work to build and test - In full-bitmap mode, nearly all the VDP is gone just for the screen, which makes file usage tricky - Worst of all, in full bitmap mode the screen has three separate tables for each third of the screen. Using my borders above, that means you also have HALF tiles to account for. Argh! For my own part, I decided long ago that I'd rather work on my own unique CRPG. Also, I would leverage it to take advantage of the platform's strengths, rather than create systems and designs that were difficult to replicate. And it would be my own work, which means any cheesy pop-culture stuff would be my own fault. As I said, though, not impossible. The Commodore 64 version of Ultima II would probably be the best version to study for a potential cross-over. It also uses a character set system for most of its graphics modes, so Chuck Bueche ("Chuckles", and the lead C64 programmer for Origin) had to solve these issues as well. Adamantyr
  7. They said it couldn't be done! Or shouldn't be... something like that. Anyway, regardless, feast your eyes on the next upcoming CRPG project, the adaptation of the notorious, infamous Ultima II, Revenge of the Enchantress! Features include: - Improved graphics over the original, with more colors! - Every original bug replicated in precise detail! No way you can get strength in THIS version either! - All hokey and cheese-ball pop culture references kept intact, to annoy a new generation of gamers! - A smaller and tighter display than the original, to give you that close-in comfort feel! Coming soon to a TI near you! Well, probably on the desk next to you. Adamantyr Disclaimer: Ultima is a totally-owned licensed subsidiary of Electronic Arts. Any usage, reference, or general thought about this product may result in immediate and fatal litigation.
  8. Technically the tool was developed for the C64, but Cartograph may suit you. It uses the same 2K of character patterns that the TI-99/4a does, and the size goes up to what you need. Check it out here: http://arkanixlabs.com/ Adamantyr
  9. I use as many comments as I need for myself right now, as I'm the only coder on my project. If I was coding for a group, I'd have more judiciously spread around. However, with assembly, most of the operations are pretty obvious as a glance; the comments are really just there to detail what particular labels mean. I actually fully commented a 6502 listing of Eastern Front: 1941 before I started trying to work on a conversion... and it didn't help all that much. The problem being that you really don't grasp WHAT the code is trying to do on a whole, only what it literally does. I wasn't able to figure out the top-down design of the AI by studying the code line-by-line, it would require a lot more research to do so. As for forgetting stuff after six months... yeah, that could happen to me too, but that's why I have spreadsheets and other tools to track a lot of the "soft" data that makes up the game engine. Adamantyr
  10. What about the concept of segments? Just thinking that you could use the equivalent of the reserve memory directive e.g. "XXXX: .res 20" would reserve 20 bytes at starting at the label XXXX in a segment to make moving things around easier. The segment base address (controlled by the linker) would be the expansion RAM, scratch pad or wherever it was needed. Yes, the Linking Loader of the Editor-Assembler accepts the following: AORG - Absolute Origin RORG - Relocatable Origin DORG - Dummy Origin BSS - Block Starting with Symbol BES - Block Ending with Symbol PSEG - Program Segment PEND - Program Segment End These are also supported by the assembler, but the EA Loader won't accept them. You have to write a custom loader yourself: CSEG - Common Segment CEND - Common Segment End DSEG - Data Segment DEND - Data Segment End Like I said, most 99'ers have never bothered to investigate these because the system isn't that great for segmented architecture. Nearly every TI application is converted to memory-image absolute files that are just chain-loaded into memory. Often referred to as 'E/A Option 5'. Adamantyr
  11. BSS - Yes DATA/CODE - No, although the assembler inherited some module-coding elements from its mini-computer roots. Not many 99'ers make use of them. Adamantyr
  12. Actually, I wasn't referring to the data section but that looks much better! I assume you mean I should have every single line (or nearly so) commented. Bah! Actually, I originally started coding on the vintage system itself, so I had a real concern that my source files (which needed to fit on one disk) may get too big if I went overboard on comments. That isn't the case anymore; I directly assemble my source files from PC files using A99 (Written by Joe Delekto) and/or Classic99's E/A assembler. However, since I'm the only coder, I don't feel the need to thoroughly comment the lines for myself, since I have a pretty good knowledge of what the different labels are and how the whole system is set up. If I was to prepare the code base for porting to another platform, what I'd probably do is write it all up in pseudo-code, rather than just heavily comment an assembly file. Adamantyr
  13. Yes, indeed I can. The TI assemblers recognize anything past the opcode sections as comments. But my favored editor (Textpad) isn't quite clever enough to treat them as comments. So I usually just use whole lines instead of on-line comments. UPDATE: Hm, actually, now I can get it to work. I still have to use some character (an asterisk works well) but I was able to make column 40 be a comment line. Cool! Edited the above to be slightly more readable Adamantyr
  14. To continue... One of the first things I did was expand my player data array so that some of my factors, such as fatigue costs, are just stored values instead of calculated on the spot. The cost in data space is cheap in comparison to the code space. The second thing was to categorize my attack/defense adjustments into a data array that is then ran through and applied for each attack type. Only a single function is used, with a switch variable to indicate the attack type. This recycles and reuses a lot of code and cuts down on duplication. So here's the new block, including the data array: * Attack routine * @ATKTYP - Attack type (0,2,4) * (Melee,Ranged,Sorcery) * @ATKDEF,@ATKDEF+2 - attacker/defender PSTATE location * @COMDEF,@COMDEF+32 - attacker/defender combat array location * @RESULT - Combat result ATTACK MOV R11,*R10+ CLR @RESULT * Populate COMDEF array LI R9,2 LI R8,ATKDEF CLR R7 ATKC1 MOV *R8+,R0 C R0,@W96 JH ATKC2 MPY @W3,R0 LI R0,PLAYER+32 A R1,R0 JMP ATKC3 ATKC2 LI R0,MONREC+6 ATKC3 LI R1,COMDEF A R7,R1 LI R2,32 BLWP @VMBR AI R7,32 DEC R9 JNE ATKC1 * Process adjustments MOV @ATKTYP,R6 SRL R6,1 MPY @W5,R6 SRL R7,8 LI R0,SPLDAT BLWP @VSBR SRL R1,4 MOVB R1,R8 LI R9,2 LI R2,ATKADJ+6 ATK0 MOV *R2+,R0 * Get affected units for check/change into R4/R5 ATK1 MOVB *R2+,R1 MOVB R1,R3 SRL R1,12 SRL R3,4 ANDI R1,>000F ANDI R3,>0020 MOV @ATKDEF(R1),R4 LI R5,COMDEF A R3,R5 MOVB *R2+,R3 * Check if spell affinity CB R3,@B128 JNE ATK1A CB R8,@COMDEF+26 JEQ ATK1B JMP ATK3 * Check targeted state ATK1A SRL R3,8 A R3,R4 CB *R4,@ZERO JEQ ATK3 * Make adjustment ATK1B MOVB *R2+,R3 SRL R3,8 A R3,R1 MOVB *R2+,R3 CB R3,@B7 JGT ATK2 AB R3,*R1 JMP ATK4 * Set the value ATK2 SB @B8,R3 MOVB R3,*R1 JMP ATK4 ATK3 INCT R2 ATK4 DEC R0 JNE ATK1 MOV @ATKTYP,R1 MOV @ATKADJ+2(R1),R2 DEC R9 JNE ATK0 * Defense adjustments for types LI R0,COMDEF+25 MOV @ATKTYP,R1 SLA R1,1 LI R2,DEFADJ A R1,R2 LI R3,4 ATK5 SZCB *R2+,*R0+ DEC R3 JNE ATK5 * Miss check MOV @ATKTYP,R1 SRL R1,1 MOVB @COMDEF+18(R1),R3 SRL R3,8 BLWP @RNDNUM MOV R4,R4 JNE ATK6 * Missed! MOV @W1,@RESULT B @SUBRET * Critical check ATK6 MOVB @COMDEF+4(R7),R0 SRL R0,8 BLWP @RANDOM ANDI R4,>000F C R4,R0 JGT ATK7 * Critical! (No defenses) SETO R9 JMP ATK10 * Defense check ATK7 CLR R9 LI R0,COMDEF+53 LI R5,4 LI R6,2 ATK8 MOVB *R0+,R3 JEQ ATK9 SRL R3,8 BLWP @RNDNUM MOV R4,R4 JNE ATK9 * Successful defense MOVB @COMDEF+49,R0 SRL R0,8 MOV @ATKDEF+2,R1 A R0,@PSTATE+4(R1) MOV R6,@RESULT B @SUBRET ATK9 INC R6 DEC R5 JNE ATK8 * Damage/debuff determination ATK10 CLR @RESULT MOVB @COMDEF(R7),R5 SRL R5,8 * Check if sorcery; add power value C @W4,@ATKTYP JLT ATK12 LI R0,SPLDAT+3 BLWP @VSBR SRL R1,8 A R1,R5 ATK11 MOVB @COMDEF+33(R7),R2 SRL R2,8 * Critical double value MOV R9,R9 JEQ ATK12 SLA R5,1 ATK12 S R2,R5 JGT ATK13 CLR R5 * Increase fatigue for attacker ATK13 MOVB @COMDEF+3(R7),R0 SRL R0,8 MOV @ATKDEF,R1 A R5,@PSTATE+4(R1) C @W4,@ATKTYP JLT ATK14 * Check if sorcery debuff LI R0,SPLDAT+4 BLWP @VSWR CI R1,2 JEQ ATK14 MOV R5,R0 MOV @ATKDEF+2,R2 ANDI R0,>0007 BL @EFFCTS B @SUBRET * Straight damage to defender ATK14 MOV @ATKDEF+2,R1 A R5,@PSTATE+2(R1) B @SUBRET * Defense adjustments DEFADJ DATA >0000,>00FF BYTE >FF00,>FFFF BYTE >FFFF,>FF00 * Attack adjustments ATKADJ DATA ATKADJ+16,ATKADJ+66,ATKADJ+104 * General adjustments (ATKADJ+6) DATA 2 BYTE 0,12,17,-1 * Attacker - Move Empowered check BYTE >22,13,17,1 * Defender - Move Weakened check * Melee adjustments (ATKADJ+16) DATA 12 BYTE 0,8,0,2 * Attacker - Melee Exalt check BYTE >22,8,1,2 * Defender - Melee Exalt check BYTE 0,9,0,-2 * Attacker - Melee Curse check BYTE >22,9,1,-2 * Defender - Melee Curse check BYTE 0,12,3,-1 * Attacker - Melee Empowered check BYTE 0,13,3,1 * Attacker - Melee Weakened check BYTE 0,20,3,2 * Attacker - Enraged checks BYTE 0,20,4,4 BYTE 1,17,18,10 * Defender - Blurred check BYTE >22,16,1,4 * Defender - Armored check BYTE >22,23,23,8 * Defender - Immobilized check BYTE >22,24,1,127 * Defender - Melee Invulnerable check * Ranged adjustments (ATKADJ+66) DATA 9 BYTE 0,8,5,2 * Attacker - Ranged Exalt check BYTE >22,8,6,2 * Defender - Ranged Exalt check BYTE 0,9,5,-2 * Attacker - Ranged Curse check BYTE >22,9,6,-2 * Defender - Ranged Curse check BYTE 0,12,8,-1 * Attacker - Ranged Empowered check BYTE 0,13,8,1 * Attacker - Ranged Weakened check BYTE 2,27,19,10 * Defender - Deflecting check BYTE >22,28,6,4 * Defender - Shielded check BYTE >22,24,6,127 * Defender - Ranged Invulnerable check * Sorcery Attack adjustments (ATKADJ+104) DATA 14 BYTE 0,8,10,2 * Attacker - Sorcery Exalt check BYTE >22,8,11,2 * Defender - Sorcery Exalt check BYTE 0,9,10,-2 * Attacker - Sorcery Curse check BYTE >22,9,11,-2 * Defender - Sorcery Curse check BYTE 0,12,13,-1 * Attacker - Sorcery Empowered check BYTE 0,13,13,1 * Attacker - Sorcery Weakened check BYTE 2,26,20,10 * Defender - Resolve check BYTE >22,29,11,4 * Defender - Warded check BYTE >22,24,11,127 * Defender - Sorcery Invulnerable check BYTE 0,13,13,1 * Attacker - Sorcery Weakened check BYTE 0,128,10,2 * Attacker - Sorcery Affinity BYTE 0,128,13,-1 BYTE >22,128,11,2 * Defender - Sorcery Affinity BYTE >22,128,17,-1 This new section and the data block take up 440 bytes and 162 bytes respectively, for a total of 602 bytes. Almost half the size, and a lot more elegant. Adamantyr
  15. I'm currently working on the combat engine portion of my CRPG. And I have come to the ultimate decision in any CRPG, or tabletop RPG... result determination. Or to put it frankly: "Did I hit him or not?" My first attempt to code up the main routine was a straight linear approach. There are three attack types (melee, ranged, and sorcery) so I made three separate functions for each. Here's that code, excluding some minor routines on the side: * Damage determination ATKDAM BLWP @RANDOM ANDI R4,>0003 A R4,@ATKDEF+6 BLWP @RANDOM ANDI R4,>0003 A R4,@ATKDEF+14 MOV @ATKDEF+14,R0 S @ATKDEF+6,R0 JGT ATKMD1 MOV @W1,R0 ATKMD1 MOV @ATKDEF+2,R1 A @ATKDEF+4,@PSTATE+4(R1) MOV @ATKDEF+10,R2 A R0,@PSTATE(R2) CLR @RESULT B @SUBRET * Attack routine * @ATKTYP - attack type * @ATKDEF,@ATKDEF+8 - attacker/defender unit (0-22 x2) * @RESULT - Combat result ATTACK MOV R11,*R10+ CLR @RESULT * Check if defender is invulnerable MOV @ATKDEF+10,R2 MOVB @PSTATE+24(R2),R0 JEQ ATTCK1 SETO @RESULT B @SUBRET * Get VDP arrays into memory ATTCK1 MOV @ATKDEF+2,R0 LI R1,HIBUFF LI R2,30 BLWP @VMBR MOV @ATKDEF+10,R0 LI R1,HIBUFF+30 LI R2,30 BLWP @VMBR * Determine fatigue bases MOV @W1,@ATKDEF+4 MOV @W1,@ATKDEF+12 MOV @ATKDEF+2,R1 MOV @PSTATE+12(R1),R0 JEQ ATTCK3 ANDI R0,>00FF JEQ ATTCK2 DEC @ATKDEF+4 JMP ATTCK3 ATTCK2 INC @ATKDEF+4 ATTCK3 MOV @PSTATE+12(R2),R0 JEQ ATTCK5 ANDI R0,>00FF JEQ ATTCK4 DEC @ATKDEF+12 JMP ATTCK5 ATTCK4 INC @ATKDEF+12 * Set attack and defense powers ATTCK5 CLR @ATKDEF+6 CLR @ATKDEF+14 * Check if attacker is exalted or cursed MOV @PSTATE+8(R1),R0 JEQ ATTCK7 ANDI R0,>00FF JEQ ATTCK6 DECT @ATKDEF+6 JMP ATTCK7 ATTCK6 INCT @ATKDEF+6 ATTCK7 MOV @PSTATE+8(R2),R0 JEQ ATTCK9 ANDI R0,>00FF DECT @ATKDEF+14 JMP ATTCK9 ATTCK8 INCT @ATKDEF+14 * Check if defender is guarding, if so, +2 to defense power ATTCK9 MOV @ATKDEF+8,R2 MOV @CSTATE(R2),R0 JEQ ATCK10 INCT @ATKDEF+14 * Set attacker's faded state to zero ATCK10 MOVB @ZERO,@PSTATE+21(R1) * Add luck to power MOV @ATKDEF,R1 MOV @ATKDEF+8,R2 A @PLUCK(R1),@ATKDEF+6 A @PLUCK(R2),@ATKDEF+14 * Branch to attack type MOV @ATKTYP,R1 B @AKCASE(R1) * Attack - melee * Get base attack/defense melee power ATKMEL CLR @PARRY CLR @BLOCK MOV @ATKDEF+8,R1 SLA R1,1 BL @FDODGE MOVB @HIBUFF,R1 SRL R1,8 A R1,@ATKDEF+6 MOVB @HIBUFF+30,R1 SRL R1,8 A R1,@ATKDEF+14 * Check player only defense elements C @ATKDEF,@W8 JEQ ATKM1 * Check for 2H weapon CB @HIBUFF+20,@B132 JL ATKM0 CB @HIBUFF+20,@B136 JH ATKM0 INC @ATKDEF+4 * Check if defender (player only) can parry ATKM0 C @ATKDEF+8,@W8 JEQ ATKM1 CB @HIBUFF+50,@ZERO JEQ ATKM0A CB @HIBUFF+50,@B128 JEQ ATKM0A INC @PARRY * Check if player can block ATKM0A CB @HIBUFF+52,@B147 JNE ATKM1 INC @BLOCK * Check if attacker is enraged (+4 to attacker power) ATKM1 MOV @ATKDEF+2,R1 MOVB @PSTATE+20(R1),R0 JEQ ATKM2 A @W4,@ATKDEF+6 * Check if defender is enraged (-4 to defender power) ATKM2 MOV @ATKDEF+10,R2 MOVB @PSTATE+20(R2),R0 JEQ ATKM3 S @W4,@ATKDEF+14 * Check if defender is armored (+4 to defender power) ATKM3 MOVB @PSTATE+16(R2),R0 JEQ ATKM4 A @W4,@ATKDEF+14 * Check for base miss * Check if defender is blurred (50% miss chance) ATKM4 MOVB @PSTATE+17(R2),R0 JEQ ATKM5 LI R3,2 JMP ATKM6 * Fetch base melee miss chance ATKM5 MOVB @HIBUFF+12,R3 SRL R3,8 ATKM6 BLWP @RNDNUM MOV R4,R4 JNE ATKM7 * Missed! MOV @W1,@RESULT B @SUBRET * Check for critical ATKM7 BLWP @RANDOM ANDI R4,>000F JNE ATKM8 * Critical! MOV @ATKDEF+6,R0 SRL R0,1 A R0,@ATKDEF+6 CLR @ATKDEF+4 B @ATKDAM * Defense checks * Check for parry ATKM8 C @ATKDEF+8,@W8 JEQ ATKM9 MOV @PARRY,@PARRY JEQ ATKM10 ATKM9 MOVB @HIBUFF+45,R3 SRL R3,8 JEQ ATKM10 BLWP @RNDNUM MOV R3,R3 JNE ATKM10 * Parried! MOV @W2,@RESULT MOV @ATKDEF+10,R1 A @ATKDEF+12,@PSTATE+4(R1) B @SUBRET * Check for block ATKM10 C @ATKDEF+8,@W8 JEQ ATKM11 MOV @BLOCK,@BLOCK JEQ ATKM12 ATKM11 MOVB @HIBUFF+46,R3 SRL R3,8 JEQ ATKM12 BLWP @RNDNUM MOV R3,R3 JNE ATKM12 * Blocked! MOV @W3,@RESULT MOV @ATKDEF+10,R1 A @ATKDEF+12,@PSTATE+4(R1) B @SUBRET * Check for dodge ATKM12 MOV @DODGE,@DODGE JEQ ATKMDM MOV @ATKDEF+10,R1 MOVB @PSTATE+23(R1),R0 JNE ATKMDM MOVB @HIBUFF+47,R3 SRL R3,8 JEQ ATKMDM BLWP @RNDNUM MOV R3,R3 JNE ATKMDM * Dodged! MOV @W4,@RESULT MOV @DODGE,R3 BLWP @RNDNUM SLA R4,1 MOV @ATKDEF+10,R1 A @ATKDEF+12,@PSTATE+4(R1) INC @PSTATE+4(R1) SRL R1,3 MOV @DMOVE(R4),@UNITS(R1) B @SUBRET ATKMDM B @ATKDAM * Attack - ranged * Get base attack/defense ranged power ATKRNG CLR @BLOCK MOVB @HIBUFF+3,R1 SRL R1,8 A R1,@ATKDEF+6 MOVB @HIBUFF+33,R1 SRL R1,8 A R1,@ATKDEF+14 * Check player only defense elements C @ATKDEF,@W8 JEQ ATKR1 * Check for Arbalest (-1 fatigue) CB @HIBUFF+24,@B139 JNE ATKR0 DEC @ATKDEF+4 * Check if defender (player only) can block * If attacker has firearm, nevermind ATKR0 CB @HIBUFF+24,@B140 JEQ ATKR1 CB @HIBUFF+52,@B147 JNE ATKR1 INC @BLOCK * Check if defender is shielded (+4 to defender power) ATKR1 MOV @ATKDEF+10,R2 MOVB @PSTATE+28(R2),R0 JEQ ATKR2 A @W4,@ATKDEF+14 * Check for base miss * Check if defender is deflecting (50% miss chance) ATKR2 MOVB @PSTATE+27(R2),R0 JEQ ATKR3 LI R3,2 JMP ATKR4 * Fetch base ranged miss chance ATKR3 MOVB @HIBUFF+13,R3 SRL R3,8 ATKR4 BLWP @RNDNUM MOV R4,R4 JNE ATKR5 * Missed! MOV @W1,@RESULT B @SUBRET * Check for critical ATKR5 BLWP @RANDOM ANDI R4,>000F JNE ATKR6 * Critical! MOV @ATKDEF+6,R0 SRL R0,1 A R0,@ATKDEF+6 CLR @ATKDEF+4 B @ATKDAM * Defense checks * Check for block ATKR6 C @ATKDEF+8,@W8 JEQ ATKR7 MOV @BLOCK,@BLOCK JEQ ATKRDM ATKR7 MOVB @HIBUFF+36,R3 SRL R3,8 JEQ ATKRDM BLWP @RNDNUM MOV R3,R3 JNE ATKRDM * Blocked! MOV @W3,@RESULT MOV @ATKDEF+10,R1 A @ATKDEF+12,@PSTATE+4(R1) B @SUBRET ATKRDM B @ATKDAM * Attack - sorcery (target and area) ATKSOR CLR @BLOCK MOVB @HIBUFF+6,R1 SRL R1,8 A R1,@ATKDEF+6 MOVB @HIBUFF+36,R1 SRL R1,8 A R1,@ATKDEF+14 * Get spell type LI R0,SPLDAT BLWP @VSBR SRL R1,4 MOVB R1,@WORK * Check player only defense elements C @ATKDEF,@W8 JEQ ATKS2 * Check for spell affinity CB @HIBUFF+19,@WORK JNE ATKS0 INCT @ATKDEF+6 DEC @ATKDEF+4 ATKS0 C @ATKDEF+8,@W8 JEQ ATKS1 CB @HIBUFF+49,@WORK JNE ATKS1 INCT @ATKDEF+14 DEC @ATKDEF+12 * Check if defender can block ATKS1 CB @HIBUFF+52,@B147 JL ATKS2 CB @HIBUFF+52,@B148 JH ATKS2 INC @BLOCK * Check if defender is resolved (+4 to defender power) ATKS2 MOV @ATKDEF+10,R2 MOVB @PSTATE+26(R2),R0 JEQ ATKS3 A @W4,@ATKDEF+14 * Check if defender is warded (50% miss chance) ATKS3 MOVB @PSTATE+29(R2),R0 JEQ ATKS4 LI R3,2 JMP ATKS5 * Check for base sorcery miss (targeted only) ATKS4 C @W6,@ATKTYP JEQ ATKS7 MOVB @HIBUFF+14,R3 SRL R3,8 ATKS5 BLWP @RNDNUM MOV R4,R4 JNE ATKS6 * Missed! MOV @W1,@RESULT B @SUBRET * Check for critical (targeted only) ATKS6 BLWP @RANDOM ANDI R4,>000F JNE ATKS7 * Critical! MOV @ATKDEF+6,R0 SRL R0,1 A R0,@ATKDEF+6 CLR @ATKDEF+4 JMP ATKSDM * Defense checks * Check for block (area only) ATKS7 C @W6,@ATKTYP JNE ATKS9 C @ATKDEF+8,@W8 JEQ ATKS8 MOV @BLOCK,@BLOCK JEQ ATKSDM ATKS8 MOVB @HIBUFF+46,R3 SRL R3,8 JEQ ATKSDM BLWP @RNDNUM MOV R3,R3 JNE ATKSDM * Blocked! MOV @W3,@RESULT MOV @ATKDEF+10,R1 A @ATKDEF+12,@PSTATE+4(R1) B @SUBRET * Check for resist (targeted only, non-damage only) ATKS9 MOVB @HIBUFF+48,R3 SRL R3,8 JEQ ATKSDM BLWP @RNDNUM MOV R3,R3 JNE ATKSDM * Resisted! MOV @W5,@RESULT MOV @ATKDEF+10,R1 A @ATKDEF+12,@PSTATE+4(R1) B @SUBRET * Damage determination ATKSDM B @ATKDAM For my CRPG design, I'm less concerned about speed than I am about space. So I'm always checking the byte count any time I finish a large block of new code. This block weighs in at 1168 bytes. Ouch. I only have about 9k of codespace left, and I still have a lot left to do, including the quest engine, NPC interaction, combat special effects... Need to trim it down! Adamantyr
  16. When I get my CRPG for the TI-99/4a finished (hopefully this year, don't hold me to it), I want to take a crack at conversion for other platforms myself. That would be an interesting way to see how much difference the opcode structure makes. Would the Z80/6502 version end up being the same size, larger, or smaller? Faster in some places, slower in others? I'd like to do the ZX Spectrum and MSX platforms for certain, and a C64/Apple/Atari 8-bit version. One good thing about Atari Age, I shouldn't have a problem finding interested volunteers. Adamantyr
  17. Dark Maze - Adam Haase DARKMAZE_11.zip
  18. You could, but you'd have to use byte-oriented operations to make it happen. The increment and decrement opcodes are 16-bit word only. Not quite. The 15-bit address line is still 64k, just in word-size, 16-bits instead of 8-bits. So all opcodes and data have to begin and end on even-number addresses. This isn't as bad as it sounds, the main limitation is that byte-sized data may end up with a one-byte loss at the end to pad it to an even boundary. The 16k RAM in the console isn't CPU-addressable, it's actually video memory. This is why TI BASIC and Extended BASIC are so sluggish; everything is passing through an 8-bit port to and from video memory. The console itself only has 256 bytes of CPU RAM in itself, the rest is gained through the cartridge port or memory expansions. (Memory expansion adds 32k in an 8k and 24k block, the cartridge port is 8k, but is bank-switchable.) You can't access the memory expansion in TI BASIC, but you have full access in Extended BASIC, although it is hard-coded to use the video memory for string and stack space, and the 24k block for program space and numeric variables. The lower 8k is reserved for assembly language subprograms, if desired. Adamantyr
  19. There was such a game in "Games TI's play", by Scott Singer and Tony Bartels. I have a copy. It's adapted from "Games Apples Play" By Mark James Capella and Michael D Weinstock. At a glance, it's pure text and written in TI-Basic. Adamantyr
  20. I didn't notice him getting faster... but I did switch him to a sprite, which is faster to process, so that may be what did it. Also, at the moment, if you hit a wall it ignores the timer check, so I should probably fix that... Yeah. Otherwise, killing the monster is ridiculously easy... he just flees to and cowers in a corner. I'd have to alter the chase algorithm, which I don't have the line space for now. The mazes create chambers now of 3x3, which makes more permissible space. But they do spend a bit more time plotting... if I threw in a random direction change, that may make it finish quicker. I hadn't done anything to slow down movement... some other factors may be causing that. The character of the game is different from the first version. Since your random chance of ending up right next to the monster was high, I introduced lives, which makes it more likely you can survive multiple levels. A point system is something else to brag about besides the level you reached. I think it was always "cat and mouse" though. My original plan was multiple monsters. Adamantyr
  21. The first accesses part of the random number seed in the scratch-pad, so it gets you two random values from 0-255. You have to call RANDOMIZE first, though. It's much faster than using RND, but I probably didn't need to bother... the game's not all that fast without CPU overdrive. The second is retrieving the current VDP timer value. I use that to check timing and slow the monster down... otherwise on CPU overdrive he's way too fast. Adamantyr
  22. Just updated to version 1.1! This should be a little more playable and less lethal. Adamantyr
  23. You may find it easier to just pick up a CF card system. Then again, you'll have to get a CF card reader for your PC, which may be problematic with older Windows versions. Windows XP I can understand, but you still run Win98? :S Gah.... Adamantyr
  24. Try putting it in a ZIP file first, and attaching that to the post. Adamantyr
×
×
  • Create New...