💾 Archived View for mirrors.apple2.org.za › archive › apple.cabi.net › Demos › SMB.GS.STUFF › though… captured on 2024-02-05 at 13:58:27.
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
Plan for Super Mario GS ________________________________________ All shapes are executable code (working) Here are the primitive routines: extern pascal void MarioInit(void); -Initializes the system. The application must make this call first. (Ob solete) extern pascal void MarioShutDown(void); -Releases all memory and shuts down tools, extern pascal void InitScreen(void); -Clears the graphics screen, sets the pallette extern pascal void SetBgndPnt(int pnt); -Set the background point to a par ticular offset into the level extern pascal int GetBgndPnt(void); -Returns the current background point extern pascal void DrawDisplay(void); -Erases the old display and draws the new one extern pascal void DrawBkgnd(void); -Draws the background fro m the Level definition -Objects in the background should have bits 6 & 7 clear. -Extrude objects should have bit 6 set and 7 clear. extern pascal void DrawFrgnd(void); -Draws the foreground from the LevelFore definition -Foreground objects should hav e bits 6 & 7 set. -background objects may be placed in the foreground definition. They will be draw in 'front' of the active sprites. extern pascal void DrawQueue(void); -Draws the shapes that have been added to the Drawing queue. This is us ed for active objects usually extern pascal void AddShapeToQueue(int X, int Y, int shape); -Adds a shape to the Draw queue to be draws the next time DrawDisplay() is called. Max 31 sprites -setting the high bit of SHAPE identifies it as a compoun d shape extern pascal int GetLevelItem(int X, int Y); -returns the shape value (low 6 bits) of a block on the Level data block. extern pascal void DrawShape(int X, int Y, int shape); -Draws a particular shape onto the screen extern pascal void Shad ow_On(void); extern pascal void Shadow_Off(void); extern pascal ContRecPtr ReadControl(void); -reads the keyboard and maps stuff to A,B,up,down,left,right extern pascal int GetShapeHeight(int shape); -returns the height in pixels of a shape extern pa scal int GetShapeWidth(int shape); returns the width in pixel of a shape extern pascal BOOLEAN IsBlockLegal(int x, int y); -checks to see if an 8x8 bloack drawn at the given X,Y will collide with either a foreground or extrude block. extern pascal v oid DrawCompound(int x, int y, int Cshape); -draws a compound shape at a particular point. - NOTE: CShape does NOT have the high bit set.` defn: A compound shape is a data block containing a variable number of three word records. The first word co ntains the X offset relative to the point of drawing. The second contains the Y offset. The last is the shape block (standard shape) number. An end is defined by an $FFFF in the shape field. example: CompoundShape dc i2'0,0,block1' dc i2' 8,0,block2' dc i2'8,8,block3' dc i2'0,8,block4' dc i2'0,0,$ffff' (obsolete) extern pascal BOOLEAN IsCompoundLegal(int X, int Y, int CShape) -check to see if all the blocks in a compound shape can be legally drawn. NOTE: CShap e does NOT have the high bit set. extern pascal void DeleteLevelItem(int x, int y) -removes the block at the specified point in the background by setting it to 0 extern pascal void SetBackItem(int x, int y, int shape) -set the specified block in the background to shape extern pascal void SetForeItem(int x, int y, int shape) -sets the specified block in the foreground to shape ------------------------------------------------------------------------- How to implement the Active shapes Primitives: void AddActiveObject(ObjectRecPtr object) -Add an object to the Active Table. void DeleteActiveObject(int ObjectPos) -Deletes the object at the specified slot. ObjectRecPtr GetActiveObject(int ObjectPos) -Returns the record of the Object in a particular slot. SetActiveObject(ObjectRecPtr object, int ObjectPos) -Sets the specified slot to object. ------------------------------------------------------------------------- Notes: Once the Active objects have been im plemented correctly, the game will be close to finished. The plan right now is to have each Active Shape have it's own action procedure. A generic action is defined and an Object Record is passed to it. All manipulation is done, and a new Object Record is returned. The shapes should be drawn according to the Xpos and Ypos fields in the record. WARNING--- All the routines use LOCAL coordinates. It seems that the Update_Screen routine is lacking in speed, once I deactivated it, the game runs ~twice as fast. Obviously, something needs to be done. A fast block routine may be OK, or a PEI based update. We'll see. The PEI Update is done. Performance is OK (20 fps @ 8Mhz). I will look into performing a PEI Block by Block Update. All shapes are now 16x13 and the playing field is 256x156 The Score and Clock are done and functioning. BUG: For some reason, the clock will randomly stop after a certain interval from 10 - 60 seconds. Hmmmmm.......maybe disabling interrupts during the clock r ead......Nope For enemy characters to be available, a message passing system will be set up. I need to figure out the particulars, but I think that setting aside a 16 - 32 block of the shape def'n table will be adequate. The shapes will be either Si mple or Compound, so a lookup table will be neccessary. The routines needed will be: DrawForeground: Modified to detect the active objects. SendActiveMessage: Tells the program "Hey!! Check me out!" ActiveMessage: Returns a struct. If first parm is NULL, no active object, one 1 can be passed at once. The modified routines will need to delete the object from the foreground after sending the message, otherwise, they will ignore it. I NEED to get all the shapes compiled. >200K of source so far :-( Well, the revision to SuperFX is coming along, the concept is sound and it should just need some minor debugging when finished. Too bad I couldn't use the old routines by passing a pointer to the vector tables to use, but that would be a HUGE mess. Better to get it working first. :) I still have no idea why the clock stops, maybe I should start up the tools with StartUpTools(ref ptr);..........Yeah, that's the ticket. Oh yea, the game is slowing down.......probably due to C code andm ultiple segments, of course no optimization has been done yet save the screen update to PEIs which was a nessesity. BTW, I think I can speed that up a bit by unrolling the loop once. ~10-20 cycles per line. New note *** IMPORTANT ***. I have decide d that compound mario shapes will be designated by 0x4--- to differentiate them from standard compound shapes which will be designated 0x8---. This is to save me from doing too much redundent code!! The new mods are taking place......... The prog ram now runs as before. I'm starting to implement the passing of active shapes to the program. When this is fininshed, the program will be in Alpha stage. Any shape >= 0x60 that is in the foreground is treated as an active shape, that number minus 0x60 will be uses as an offset into a list of shapes that are 'Active' shapes, either simple or compound. The shapes must be revelant to the normal shapes and Compound tables, Mario cannot be used as a valid shape number, i.e. no 0x4--- numbers. An odd b ug has come up, while messing with the mushroom location, it seems that a big mario crashes the system. I must investigate. Oh yes, the message passing sort of works. A message gets across, but I can't get anything to appear. Found the bug, it was a major one, too. I don't know how things worked as well as they have. When I grabbed 4 bytes from the stack, I was adding instead of subtracting from the stack pointer. I can see how that worked, but it was luck. More big problems. Whenever a new object is added, anything on screen vanishes. I traced the bug to the fact that I was using the same object record for everything, so each object pointer was pointing to the same spot in memory, that way, whever a new object was added, it was automatica lly duplicated. I've decided to rewrite the routines in ASM to make it more understandable. :) Writing stuff in ASM was not necessary. I redefined the C code to use an array of Object RECORDS instead of POINTERS. the pointers did nothing since I di dn't know what they were pointing at! Probably was causing some crashes. All the message passing works and new stuff is getting drawn, the mushrooms seem to work for now. The only big stuff left to do is get all the shapes in. Ughhhhh!!!! Also, the game has REALLY slowed down. I kinda want to find out why first, but I still need to add invisible blocks, coins, vines, etc. I think I'll go work on the shapes right now. -------------------------------------------------------------------------------A few months later..... Some quick thoughts of the SMB ressurection: 1) This engine will be MUCH faster for several reasons a) The screen will actually scroll. No Draw/erase/update loop b) Background stuff can be drawn in bank 1, but moving shapes will need do be done in Bank $E1 I've done all the changes I think I need for now. I used a pla/DP sta for scrolling, it appears to be only slightly faster than a DP lda/sta. I'll forget that for now. Time to go through and clean out the code, trim it down, etc. Tomorrow I'll start to redefine the level so that a 16-bit val is used. 2) Well, the initial changes are made. I must say that I am impressed by the speed of the new version. At 2.8Mhz the screen moves about 24 FPS and over 40 FPS at 7Mh z. In fact, this will have a few speed ups not present in the old version because whole shapes can be used instead of just blocks. 3) A new thought just came into my head. I don't need to keep the erase routines. Why, you ask. Because the shapes are AUTOMATICALLY erased when the background is scrolled. To solve the problem of 'hiding' behind objects...since the screen does not scroll at that time, I can just selectively update the area that mario is on. Happy day. One other thing, to facilitat e a smooth screen update, I may sort the foreground objects by their Y-postition. That way, as each scan line is updated, a shape a can be draw also. That would make the whole update one clean 'wipe' of the screen. Quick thought. Since there won't b e any automatic clipping done by the screen update, I need to black out all the palettes above and below the min and max values. That should do it. If I wanted to, I could eliminate the separate fore/background screens. Yes, I think I may, because the way this engine is working, there is no advantage to keeping them in their current incarnation. Well, the foreground is eliminated along with LOTS of code that delt with back/foregrounds, erasing, drawingQueues, etc. This is almost a complete rewrit e. I finished a scroll routine that scrolls to the right. It uses PEI's and is over twice as fast as the PLA/STA version. I wish I knew a way to implement left scrolling using PEI's. I should ask around. I've been working on a level editor. Things were going great until I suddenly started to get mysterious crashes. That will be investigated very soon. I think my array indexing is screwed up. I need to start re-compiling the shapes to use Bank $E1 for writing. This is really a pain in the Ass !! I'm just going to get Mario walking around and breaking brick and screw anything else for now. I wish I knew the best way to do this Scrolling/screen updating. I'm not sure if I should switch to a draw/erase/update or keep the draw/draw. I think th e d/e/u could be have less tearing, but the draw/draw rips along about twice as fast. Arrrgggghhhhhh.........I hate decision making. ...3 months later I just decided to do some work on this stuff again. I can't even remember what any of this code does anymore. Time to relearn. I'm beginning to recode the Queue, Update, and scroll routines to integrate scrolling and updating of sprites. This should make screen updates smoother, but I don't think I'll ever be able to do a 1/60 second wipe beca use of the additional overhead. The changes are made but untested yet. I really don't want to test it because it'll probably not work and I'll have to debug this unstable crap. Oh, the AddShapeToQueue is incomplete. whatever shape is given, the heig ht needs to be loaded and added on to the Y-coord so that the shape is drawn _after_ the lines it resides on are drawn. The initialize screen routine needs updating too so that all lines above and below the playing field are black. Well, it's all don e and debugged and I must say the results aren't too bad. I am still getting a bit of flicker, but I'm planning to do some syncing later on that should eliminate a good chunk of it. I may add a flag in that will allow the person playing to choose whethe r the program will run faster w/flicker or slower w/o flicker. The non flicker version will probably run at 12-15fps tops as the scroll/update loop is sooper fast but takes ~3 vbl cycles + 2 VBLs for sync. When I get around to doing this I may set the s ystem to 50Hz and see what that does for me. (Note: 5 months later- Flicker is taken care of by eliminating the integrated scroll/draw routine. However the old draw/scroll/erase loop is back :( ) Maybe for shits & giggles I'll make a quarter scree n version of the game when I'm done and see how fast it runs :) (60 fps) I'm planning to make the ScrollR routine work with a page-aligned DP so it will run as fast as possible. The only way to make it effective is to make a precomputed table with th e DP for each line and offset. Since not all lines will be able to use a page-aligned DP. if the value is >$8000 then the DP should be set to $2000+(val-$8000). Well, the page alignment will probably work, but that's an end-of-the- road optimization . Right now I need to get the game to the point it _was_ at 1 year ago. Things are progressing once I have mario moving well, it should only take a few hours of work to get the rest up-to-date. Later I think I might triple-buffer the game to get it to scroll smoother, the background shapes will need to be recompiled so that the background can be in (for example) Bank $02, then the screen is scrolled onto Bank 1, the foreground shapes are drawn, then the screen is updated 1/60 sec update :) The scr olling will take ~twice as long plus the time to copy screen scroll via abs indexed: lda $2000,x sta $2000,y sta $00,x => 7 cycles/byte (same as MVN or MVP) Well, it's been a while since I wrote anything here. I am happy to say that it looks li ke the game might actually be finished. Mario is moving smoothly and I just need to re-implement the message passing functions from last year. There are 2 MAJOR things that must be done before I will really feel that the project could be released: 1) A good level format. Having the level just be a raw bunch of data is not satisfactory. I need to work in the concepts of warp tubes and multi-segment level and the link between them. 2) After a level format has been decided on, making the level editor. Level format: (obsoleted) note - levels may be a max of 64K The first segment reference (SegOff1) will be where the player initially starts Offset type Identifier Description ----------------------------------------------------------------- -------------- HEADER: String "SMBIIGS" Identifier string for a level file CString Level name i.e. "World 1-1" byte NumSeg Number of segments word SegOff1 Offset into file of first segment word SegOff2 Offset to second segment . . . word SegOffN Offset to Nth segment byte NumExtSeg Number of external segment references CString ExtSeg1 filename of first external ref CString ExtSeg2 filename of second external ref . . . CString ExtSegN filename of Nth external ref SEGMENT: string "SMBSEG" Identifier string word BgndClr Color of the "sky" (RGB) word SegWidth Width of segment in blocks word PlayerX Block where player begins word PlayerBase Baseblock where the player begins byte[32] SpriteTabl e Enemy sprites to be used in this seg. byte[32] Palette Palette to be used for this seg. word NumRef Number of segment references word RefOff1 Blocknumber ofsegment ref word SegRef1 Segment to link to word RefOff2 Blocknumber word SegR ef2 Segment to link to . . . word RefOffN Blocknumber word SegRefN segment to link to data LevelData 13*SegWidth bytes -------------------------------------------------------------------------------- NOTE: If a segment reference in a give n segment is >0x00FF, then the low order byte should be ignored and the high order byte used as an index into the list of external references. ex. RefNum 0x0300 ExtRefList "World11" "World31" "Bonus" "World71" In this case, the next segment loa ded would be the main segment of the SMB world file "Bonus". I'm doing a quick modification to the scroll routines. I've been adding in same zero to buffer the data, but that shouldn't be necessary. The screen is 16 blocks wide _PLUS_ 2 column that get scrolled in. So when calling DrawDisplay, the valid range of values would be 0-17 (18 total) with 1-16 being the visible on screen blocks. (Note: The scroll problem was caused by DrawDisplay not drawing background blocks (ID = 0)) Fixed scroll ing, all I had to do was put the call to DrawDisplay before Scroll. Ignore the above paragraph. It was the ramblings of a madman. Done with finals, so I'm dedicating today to getting stuff done. I found out that turning on compiler optimizations REALL Y sped things up. I'm running smack into the 64K limit that I set for myself. Oh well, 50K of that code is compiled sprites. I put one-ups and power stars in. They work very well. Also, the pointsProc was ported in. I think I'll add invisible blocks too. I still really need to implement the message passing mechanism. Found a REALLY nasty bug. For some reason, I couldn't get the Big and Small Mario's to agree on where they wanted to stand. Spent 2 hours looking for something subtle. Finally chan ged the Height value of jumping mario on a whim and it worked. This is a bug that needs to be corrected. I'll track it down later. But for now just making a note that BigMarJumpL & R are 1 shorter in height than theu should be. Found the problem.....I wasn't recomputing the height of a sprite when it needed to land. If the jumping and standing sprite were different heights, then there was an error in the calculations. Stupid, stupid, stupid. Invisible Blocks are in and so is the message passing syst em. The message passing may be eliminated later and a direct call to AddActiveObject made from DrawBkgnd. But for now it works, and I'll work with it. Everything is fine. I've got a lot of things done. The Question blocks are in, fireballs work, mess age passing is OK. I found out that I need to generalize out the routines for handling mario's collisions with background objects. I think I may make coins their own sprites, rather than mess with a lot of special cases. Coins are done and they work we ll. I wrote a routine that any sprite can call to find out if it has run into Mario. This made it really easy to add collision detection to the enemies. I'm in the process of changing the routines that access the LevelArray. I'm setting the array to a pointer that can be accessed. LevelPtr and LevelHeight are global variables and are all that are needed to generalize the level stuff. Also modified InitLevel, it now sets LevelPtr and LevelWidth instead of copying a block of data to LevelArray. One quick note: With compiler ooptimizations on, the game runs ~33 frames per second @ 7MHz. 17 fps @ 2.5 MHz Working on little things that need to be done, invisible support is almost done, I just need to find a way for it to be triggered ONLY when the block immediately above the player is the invis. block. Soon I'll add in the final mario shapes, fix the mushroom shapes and add more backgrounds. Invisible blocks are now handled properly. I also broke mario.cc into several files so compiles are fast er. I spent a few hours going through and cleaning up the objprocs source. What a mess!! I can;t believe I wrote that crap. I had 2 routines to handle the Koopas, one for left, one for right. 99% of the code was identical!! Needless to say, they are now happily combined. I'm going to add fireball collision support so that I can kill things with them. Right now they look cool and all, but are pretty much worthless. Oh, I bagan a conversation with David Ong Tat-Wee (?) anyway, the guy who did DOTW. Cool game, great animation. I hope he can help me finish this up. I really need someone to do some sort of intro screen and such. WOW! David is a cool guy. Pointed me toward some other IIgs people. Hope they're as friendly. :) Oh, what did I do tod ay? Well, the fireballs are working quite well and I fixed a couple of cosmetic things. All I really need to do now to make the thing releasable is draw 8 more mario shapes (big/small skid,climb) and add support for the turtle shells to knock stuff down . Just gotta do it. Though on DOTW stuff: Using the new sprite compiler to redo the shapes could theoretically save me 1 cycles/word over a PEI based update which comes out to a time savings of 21632 cycles/frame which is around 7.7 ms. Right now the thing runs at ~15fps => 66.6 ms/frame. This savings would push me to 17 fps. An increase yes, but combined with the fact that not all of the screen would have to be redraw every frame, the speed could bumped up to ....Holy $!#@.....40fps for just scroll ing. I could make it smooth using the 1/30s VBL trick. This could work out well. And that 40fps is assuming the screen is 75% full. Throwing DP LDA/STA sprites on top could make it slower by about 5fps, but who cares. I've decided to redesign the low -level stuff again so that I can make use of David's techniques. Also, I'm simplifying things a bit. UpdateScreen is gone as it will no longer serve and purpose. Also, I'm going to eliminate PassMsg and ChkMsg. Eventually, the enemies for a level will be help in a separate data struct, but for now, DrawScreen will call AddActiveObject itself. Just looked at all my background sprites. They are all masked. Arrrgggghhh!! Now I need to recompile them any way. Oh well, good excuse to use DSC. Been doi ng a lot of work. I changed some major stuff and got an extra 5fps at 2.5MHz. :) Just some minor fixes to what's there and it'll be good to go. All I need to do now is figure out a good may to clip stuff. Maybe disabling shadowing and the drawing only the edge block, then updating the edge. The thing is fast >17fps @ 2.5MHz. OK, I've got a way to do the scrolling and stuff that I'll stick to (maybe) Maintain 2 different update arrays, one for drawing blocks, the other for scrolling. The one fo r blocks will only draw the blocks which change (i.e. right-side, blocks under sprites). The PEI array will tell which block sections need to be scrolled. Redundent sky blocks don't need it. This will make other things a bit faster, too. There will be less overhead in the Scroll routine and DrawQueue and AddShapeToQueue can just fill the Queue up without having to link it to the scrollarray. In fact scrollarray can be done away with!! To get an idea of the speed up, right now, worst case, the whole screen is done using pla/sta = 8 cycles * 64 * 169 = 86000 cycles + sprites. Each sprite is about 800 cycles(?) so for 16 sprites = ~100000 cycles just for screen drawing. For the new method, lets assume 5 blocks per sprite and each block is 390 cycles. So for sprites 800*16 + 5*16*390 = 44000 cycles and for a 75% full screen = 48*169*8 = 64000. So the new method will be about the same as the old in the worst case. In the typical case we have now with only mario plus one sprite on screen, old way = 88 000. New way = 70000. And if I do it in Bank 00 eventually, I save 2 cycles/word fo screen update so new way is now only 55000 cycles in a moderate load and in worst case (Full screen, 16 sprites) = ~100000, So we get 30 fps :) @ 2.8 MHz Adding in req uired stuff. Pipe warping is coming along. No effects, but the basic mechanism is working. Also, I redid the I/O routines to use GS/OS instead of the built-in C functions. It's a lot faster now. Also fixed a bug in the goombaProc. The goombas weren' t falling, just floating off in mid-air. Weird. OK, I've fixed the fireball and goomba float bug. Transition effects are in and I'm ready to begin the graphics redesign. The sequencer to do each frame should be: 1) Add the shapes 2) Draw the display 3) Scroll things in (max 5 bytes) I'm back after about a month and a half off. Good Lord I didn't want to deal with this stuff. I've had time to think about the graphics, and I think my best intermediate option is to clean up the clipping, then worry about absolute speed. What I plan to do is do an erase/draw/scroll type thing. This way, I can do proper clipping, but still get most of the speed out. It'll be just as if the number of sprites on-screen doubled. There should be no flicker anymore as well. It works!! No flicker and sprites are clipped. I just need to work out problems with the erase part. I tried a couple of approaches, but I think I'm going to modify DrawScreen to take a variable X and Y range and use that. Done and looking good !! I'm going to pull the enemy shapes out of the level data and make a new struct for them in the file. It's just too limiting forcing enemies to be where there is no background and also, it broke in the new stuff. :) Oh yeah, World 1-1 in completed, th e flagpole isn't working, but it's all there I _Really_ need an editor. Hand coding in about 2000 hex values is not fun. Oh yeah, I found a glitch in my AddActiveShapes routine. Seems it was not skipping non-entries in the ObjectTOC Table. Fixing this gave me a few extra FPS. Probably was causing some crashes, too. Which reminds me, the program crashed upon exit if optimizations are turned on. Humph! Sprites are back and better than ever! The new method of includeing them in a separate part of the Segment is really nice. No limit of 16 baddies/segment. Now the full (256) range of sprites is possible. This can be kicked up to 65536 easily. I've been doing a bit of tweaking and bug fixing. Coins are _finally_ implemented. They are Background sha pes. Period. No more changes. It would have been too much of a slow down to force them to be sprites. The erase/draw per frame was too high of a price to pay. Now any number of coins can be on a segment without slowdown. I'm having a bit of trouble a llowing the coins to be detected. But, I never finished the HitWhileFalling, Right and Left. So...... Next on the agenda. Covering up mushrooms and stars coming out of blocks and working on Mario's transitions (Up/Down pipes). Also need to finish the Pipe shapes. Thing are shaping up!! Sidenote: The ideas about doing a selective update are still hanging around, but the current incarnation is that it'll be done 1 line at a time with each line divided into 4 secons each 32 bytes wides. If a block sho uld be updated, then that section is marked. I will have to do 5 different scroll routines to handle all 16 permutations. i.e. 1000,0100,0010,0001 can be handled by the same routine, just different starting address. 1010 and 0101 are the same. 1100,011 0,0011 same and 1110,0111 same then 1111 and 1001 to clean up. Of course the game will slow down with more blocks, but I think it'll be worth it. Coins are done, nice effect, too. :) I think I'll try profiling. OK, time to speed things up. First, alg orithmically. I'm going to go through and change all the while(IsShapeLegal()) ++val stuff. This is waaayyyyy too inefficient. It can be rounded to the nearest block I think. Should remove potentially a lot of computations. Well, that was changed. A few problems crept up, but they're squashed. The next big thing will be doing the selective scrolling. Shouldn't be too hard, but need a lot of special case code. Selective scrolling sucked! I couldn't get it to work, so it's on the back burner for n ow. Time to get mario coming _up_ pipes and doing the flagpole thing. Oh yes, I can now compile with optimizations on. I had forgotten to put an rtl after my ClearScreen routine, don't ask how. Dumb, dumb, stupidhead. OK, back to work after taking a m onth off. I'm finally getting around to doing things that need to be done. I just finished implementing the flagpole. I decided to make it a virtual sprite; height and width defined, but no drawing It worked well. I think I may do this for invisible bl ack, too. That could eliminate a lot of special case code in my jump routines. Thinking about the level format. I need a way to determine where a pipe leads to. All I can do now is restart the destination segment over again. This is no good. Also, l ater I will need to know if it is a vine or a pipe destination So, I think I'll extend the level format and add an identifier to each segment reference as well as an X and Y block parameters. For vines, only the X block is important, but for pipes, these coordinates will determine the left-hand edge of the exiting pipe. This will allow for correct transitions. On second though, I don't need an identifier. Since the program checks for the presence of a pipe block below the player, I can just add a check for onVine() and then do the transition if the player is above the screen (playerY < 0) NOTE: To pull most of the stuff above together I'll review where I'm at in the coding of the game. 1) The 'substance' of the game engine is done. The last 5% ne eds to be done which, of course, is the hardest to finish. 2) My method of scrolling and updating is frozen. I _may_ come back to it after everything is done, but probably not. I experimented with only updating every other line, and that worked. I may add that as a command line option for people with stock machines. 3) The level format is almost frozen. Just need to flesh it out for supporting a few special cases. 4) Most background shapes and enemies are drawn, but not compiled. 5) No thought to water worlds has been given, but shouldn't be _too_ hard. It's mainly a matter of adding a inWater() predicate and some special case code in the jump routine. Eureka!! - Just had an idea that'll save me 1 cycle/word on the scroll routine. Instead of operating on 1 word at a time, I can cache 3 words of data in the Acc, X and Y reg. Then I can push them on the stack to scroll and still stay ahead of the data. This only work because I've limited scrolling to 5 bytes (10 pixels) at a time. The max I could do here is 12 pixels at a time. This will save me a little over 10000 cycles per frame. Which at 15fps gives an extra 1-2 fps. Yeah. Note: I might be able to use the D reg as well with an LDA/TCD as an effective LDD instruction Just implemented it and it gave the expected results: a 10% boost from 15fps to 17fps @ 2.8MHz. Who knows, maybe I can optimize it a bit further on. :) I think 20fps is definitly possible since most of the code is in C. Once the routines that are called most often (MovePlayer, FindShape, etc.) are assemblized, that should give me a little boost. I may try to do some DP aligned code later on and handle certain lines as a special case. I think I only need 5 cases to han dle all the lines. Since they'd be special cased, I could DP align all of them and give myself another 10+% boot up to 19fps. Hmmmmm......4 cycles/DP load, 4 cycles/ph<axy>. That's getting close to a naive PEI solution (7 cycles/word vs. 8). Of could a DP aligned PEI scroll could pull 6 cycles/word and beat out my code by 25%. You know, if I hammer off another cycle/word, that's a greater than 10% boost. I just went from 10 cycles to 9 cycles which is 10%, +/- 1% for the rest of the code. Going from 9 to 8 is a 11% boost which at 17fps gives me 19-20fps. I'll do the DP aligned stuff tomorrow. :) NOTE: going to a DP PEI would give 21-22 fps. Well, I just compile a few more shapes. I think I'll work on getting the rest of Mario's actions down. (D ying, invinsible for 3 sec., etc.) Allignment bug creeping up again in SpawnObject. I don't know why, but I cannot get spawned sprites to allign to the block boundaries. I used the same formula as for static objects like breaking bricks. Maybe it's wh ere I'm calling SpawnObject. Because the problems directly correlate to the players X velocity. Well, some finish is done. Mario now 'dies' correctly, popping up and down. I cleaned up the pipe transitions a bit by inserting a 1/2 sec pause between scr eens. Looks better. The next big thing to do is add support for water and then finish coding object procedures. After than it'll just be a matter of tuning performance to the point where I can add sound. Speaking of which. At first I'm only going to have sound effects for jumping, skidding, growing, explosions, etc. Later on when I add the music track, I'm planning to use VBL interrupts to time my music. So it'll have a resolution of 1/60th sec. This should be OK and provide me with a low-overhead solution rather than sucking up a lot of interrupt time processing the sound registers. W ent in and removed 2 CLC intructions from the Scroll code. I don't think I can really speed it up anymore without using tables. I only saved 4 cycles/line which is 676 cycles/frame. quite a bit less than 10,000+, but a savings. At 17fps, this gives 11 ,000+ cycles saved. Good for 1/8 of a frame. FPS boosted by .13 Now I need to give thought on how to 'bounce' blocks when they're hit. Did some math earlier. 60% of the CPU time is given to the scroll procedure. Even with a PEI update, I could only ge t about 25fps. So, this means I need to trim down the rest of the code. I'll have to do that later after everything is working (famous last words). If I can keep the game logic under 15000 cycles per frame, I'll have a good chance at hitting 30fps. We ll, I can't speed up the scroll code anymore, so a lock down of <30fps is in effect. Shooting for 25. Bouncing bricks are in. Not too hard, really. Also added in the coins that pop out of the ?-blocks. I've got a new idead about handling collision de tection as well. Right now, every time a sprite check for collision with fireballs or shells, etc. it searches through the whole sprite list. I think I should just go thought the sprite list once and do the collisions by type. That should help speed up the object procedures. Right now, getting a lot of sprites on screen slows things down quite a bit, but only when they're goombas or koopas. Found a _real_ good spot to optimize. Every time ISLEGAL is invokes, it makes calls to GetLevelItem for each b lock a sprite is on to check for collisions. Well, GetLevelItem calls Mult320 which really multiplies by the levelwidth, so the program is doing several dozen multiplications per frame. We can do better. Since the only values passed to Mult320 are 0-12, we can precompute a table for them. Should help out a bit. Well, the framerate doesn't seem to drop _quite_ as much when there are 3 goombas on screen. Didn't hurt any. Need to get in and recompile a bunch of shapes. A lot of shapes are still drawn using Absolute Addressing when they should use DP. This is a holdover from the good 'ol days of drawing directly to Bank $E1. Of course, I _should_ get all the shapes in first. The swimming and climbing pictures are draw, I just haven't gotten them in yet. Of course I've still got spineys, squid, cheep-cheeps, bowser, bullet bill to compile as well. The only pictures I don;t have drawn yet are the second frames of buzzy beetle and spiney eggs and the hammer bros. Oh year, Bowser's fireballs and the fireballs-on-a-stick. Quite a few backgrounds from later levels as well. Took some time and cleaned up a bit of code. Little changes that made it a bit samller and I also added in multi-coin blocks. They work reasonably well, but the framerate drops if there are > 6 sprites on screen. Oh well. I'd be really nice to be able to start over and use my new no erase architecture. Maybe in the future... Thinking of re-doing the MovePlayer routines. I'm pretty sure that the 'stuck- in-the-brick' bug is bec ause I'm doing separate colision checks for horizontal and vertical movement. I need to check on both and get rid of the table math for jumping. It's too hard to stop the player from other routines. Did some work tonight. Things bouncing off of bricks when hit from below works. Also, the power-up bricks bounce before delivering their goodies. I Think I can put 1 PEI intruction in my scroll code. This will save 2 cycles/line or only 320 cycles/frame. At 17fps = ~5400 cycles/second. Yawn. I'll do i t anyway. Tomorrow if time permits, I'll make background versions of the mushrooms and one-ups and power stars. I'll also redo all of the routines that control the player's movement. They're too complicated. Too many calls to isLegal are made. This r outine takes up a lot of time. Less now that the multiply was optimized out, but it is still horrible. I'm going to make the routines more reactionary. instead of carrying information from frame to frame, it'll just look at the current position and X & YVel to see what to do. Went in a made the scrolling code more interrupt friendly. It not re-enables interrupts after each scan line. This slows things down a bit, but I think it's the Right Thing to do. Anyway, I'll need this when I add music later.A lso, I'm cleaning up the way to move that character under computer control. Fleshed out FindShape to handle climbing. FadeIn works now, also fixed when the fireflower comes out - adjusted its starting Ypos. TODO: Finish flagpole anim. Fix color discre pencies. Clean up some shapes. Then World 1-1 is done! Oh wait, add intro animation. Easy. Well, I was going to DP align my scroll code, but I forgot that I changed the DP depending on how far I wanted to scroll. I could still do it, but I'd need to write 40 different scroll routined to handle all the case. (8 address allignments and 1-5 byte scrolls; 5*8 = 40). I'll probably still do it. OK, I only need to do 32 special cases, 'cause the cache technique only works for scrolls of 4 bytes or less. A lso, I got the marquee thing done and fixed my scoring problems. I'll compile in the marquee and make the intro scrolling code. And I'll clean a bunch of other things up. It's getting there. I'll also probably do the DP aligned stuff tomorrow as well.