+SpiceWare Posted November 29, 2017 Share Posted November 29, 2017 http://atariage.com/forums/blog/blog-148/cat-226-stay-frosty 1 Quote Link to comment Share on other sites More sharing options...
vidak Posted November 29, 2017 Author Share Posted November 29, 2017 Thank you!! Quote Link to comment Share on other sites More sharing options...
vidak Posted December 2, 2017 Author Share Posted December 2, 2017 (edited) I need some help. I have two issues: How the Variable "Heights" Works in Stay Frosty One thing doesn't add up in my analysis of how the Y Register in the Stay Frosty kernel is formed. This code forms the Heights variable: LINE 2196: ldy #SECTIONS*DATA_BYTES_PER_SECTION-4-1+2+2 ; -4 for the 4 unused platform bytes ; +2 for fireball size info ; +2 for level control init .plLoop lda (LevelDataPtr),y sta Heights,y dey bpl .plLoop The SECTIONS constant equals 5. The DATA_BYTES_PER_SECTION constant equals 11. Cancelling out the minor adjustments, the first LDY operation should load Y with 54. As we know from the previous blog post, the LevelDataPtr is pointing to the Level1 label in ROM. The first inconsistency is this: There is only 53 bytes of information apart from game logic in those sections of ROM. The second inconsistency with my analysis is: there are only 6 or 7 bytes of information in ROM under those labels that could be construed as the Height of things. The third inconsistency is this: There are only 5 bytes set aside for Heights in the RAM. This equals the number of sections of Height that the variable is supposed to store. The STA operation in the above code is using Absolute Indexed addressing. This means the Y register is used to increment the memory location relative to Heights, not the value in the Heights memory location. This means if we increment the memory location more than 5 times we are starting to store data in other memory labels than Heights. I am thoroughly confused. If anyone can help me understand this, I would be very grateful. I feel as if I don't understand the order of operations being done with the constants in the first LDY operation. I also don't understand what DATA_BYTES_PER_SECTION refers to. I cannot find any groups of 11 bytes of data anywhere. Preparing the Graphics Pointers for Sections 1 to 4 How does this code work? LINE 2006: ldx #0 ldy #0 pfLoop clc lda FrostyImagePtr,y adc Heights,x iny ; 1 iny ; 2 sta FrostyImagePtr,y ; Graphics Address (0) + Heights -> Graphics Address + 2 dey ; 1 lda FrostyImagePtr,y ; LDA Graphics Address + 1 adc #0 iny ; 2 iny ; 3 sta FrostyImagePtr,y ; Graphics Address + 1 -> Graphics Address + 3 <Repeated Process for the Mask and Colours here> dey ; 2 inx cpx #SECTIONS-1 bcc pfLoop I think what is happening in the above code is this: We loop through this above code 5 times - as many times as there are bands up the screen. (5 times) Everytime we move through the loop, the Y Register increases by 2. So the 5 times we move through the loop Y increases through these values: 0 -> 2, 1 -> 3 2 -> 4, 3 -> 5 4 -> 6, 5 -> 7 6 -> 8, 7 -> 9 8 -> 10, 9 -> 11 This means we are increasing the graphics pointer memory address by 2 every time--both the lower byte of the pointer, and the higher byte. We are shifting the line of graphics by 2 up every band of the screen. This is confusing - why do we need to do this? What seems to be happening to the lower byte is that we increment its memory address by the number of bytes equal to the height of the band. Why don't we also do this to the higher byte? Wouldn't this lead to the lower byte increasing something like 30+2 locations forward, where the higher byte only moves 2 locations forward? I need some clarification on the above issues. Edited December 2, 2017 by vidak Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 2, 2017 Share Posted December 2, 2017 Been a long time since I wrote this. Was under major time constraint, as I was invited to join the project on October 29th, so comments aren't the best. Let's see what I can figure out... I'll do this as 2 separate replies. First up - How the Variable "Heights" Works in Stay Frosty here's the level 1 data that'll be copied into RAM Level1 .byte 35,35,34,34,10 ; section heights add up to 148 .byte 80, 0 ; section 0 fireballs .byte 80, 100 ; section 1 fireballs .byte 0, 0 ; section 2 fireballs .byte 0, 90 ; section 3 fireballs .byte 0, 0 ; section 4 fireballs .byte %00000000, %00011111; fireball size ; no section 0 platform - bottom of screen is fully on .byte 0,zzX_______,zzXXXXXXXX,zz_______X ; Section 1 platform .byte 0,0,zz______XX,zzXXXXXXXX ; Section 2 platform .byte 0,zzXXX_____,zzXXXXXXX_,0 ; Section 3 platform .byte 0,0,0,0 ; Section 4 platform .byte 0, 0,0,zzXX_XX_XX ; Section 0 ice .byte 0,0,zzXX_XX_XX,0 ; Section 1 ice .byte 0,0,zz_______X,zz_XX_XX_X ; Section 2 ice .byte 0,zzXX______,zz_XX_XX__,0 ; Section 3 ice .byte 0,0,0,0 ; Section 4 ice .byte 0,0 ; level control I count 55 values in there, not 53, so a miscount could be contributing to some of your confusion. As a side note - the zz constants are in graphics.h, I used to use those for graphic data so I could more easily see the graphics within the code. I now let jEdit colorize binary for me, which is even more legible than using the zz constants: The bit of code starting at line 2196 is what copies level data from ROM into the following RAM: SECTIONS = 5 ; sections 0-4, 0 is bottom area just above score DATA_BYTES_PER_SECTION = 11 Heights ds 1*SECTIONS ; heights of the levels FireBallX ds 2*SECTIONS ; fireball positions, 2 per section ; x=0 means no fireball FireBallSize ds 2 ; 1=large, 0=small Platforms ds 4*SECTIONS-4 ; platforms IceData ds 4*SECTIONS ; ice blocks LevelControl ds 2 ; level specific data-moving platform state, etc) The first part of the data is Heights, which is why the loop uses that label, but it's copying all of this data not just the Heights. There's (1*5) + (2*5) + 2 + (4*5 - 4) + 4*5 + 2 bytes there, 55 bytes. SECTIONS*DATA_BYTES_PER_SECTION-4-1+2+2 = 54. Looks off, but it's not because 55 bytes will be copied when Y decrements from 54 as the use of BPL means that Y will have a value of 0 the last time through the loop. If BNE had been used then only 54 bytes would have been copied. DATA_BYTES_PER_SECTION refers to the 4 with SECTIONS: Heights ds 1*SECTIONS ; heights of the levels FireBallX ds 2*SECTIONS ; fireball positions, 2 per section Platforms ds 4*SECTIONS-4 ; platforms IceData ds 4*SECTIONS ; ice blocks 1 + 2 + 4 + 4 = 11 so SECTIONS*DATA_BYTES_PER_SECTION-4 refers to that amount of data for Heights, FireBallX, Platforms, IceData. The bottom-most platform is always fully on, so no data is needed hence the -4. The +2+2 refer to what's left: FireBallSize ds 2 ; 1=large, 0=small LevelControl ds 2 ; level specific data-moving platform state, etc) while the -1 is due to using 54 to 0 for the copy loop instead of 55 to 1. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 2, 2017 Share Posted December 2, 2017 Next up - Preparing the Graphics Pointers for Sections 1 to 4 The data being used is this: Heights ds 1*SECTIONS ; heights of the levels ... FrostyImagePtr ds 2*SECTIONS Which you can also think of as being: Height0 ds 1 Height1 ds 1 Height2 ds 1 Height3 ds 1 Height4 ds 1 ... FrostyImagePtr0 ds 2 FrostyImagePtr1 ds 2 FrostyImagePtr2 ds 2 FrostyImagePtr3 ds 2 FrostyImagePtr4 ds 2 the bit of code starting at line 1975 sets FrostyImagePtr0 Then the bit of code starting at line 2006 sets the rest like this: FrostyImagePtr1 = FrostyImagePtr0 + Height0 FrostyImagePtr2 = FrostyImagePtr1 + Height1 FrostyImagePtr3 = FrostyImagePtr2 + Height2 FrostyImagePtr4 = FrostyImagePtr3 + Height3 As far as how it was implemented I'm sure there's better way to do it than all those INY and DEY instructions, but due to the time constraint we were under once I got a routine that worked I went on to the next. The heights are all 1 byte values. The way to add a 1 byte value to a 2 byte value is this: add ds 1 value ds 2 ; value = value + add clc lda value adc add ; if (low byte of value) + add > $ff then the carry flag gets set sta value lda value+1 adc #0 ; ADC = ADD with Carry, if the carry flag is set this will add 1 to the high byte sta value+1 so that ADC #0 instruction is taking care of the higher byte. ADC handles a carry, which is why you should always clear the carry before the initial ADC for the low byte. For the typical kernel loop you'll set Y to something like 180 at the top, then count down to 0 after which you'll have a separate kernel to draw the score. For Stay Frosty this count down is done 5 times, once for each section. This is kind of hard to see because I used a macro, found at line 123: MAC SECTION .SEC SET {1} ldy Heights+.SEC ; load Y with height of current section lda #ICE_TOP_COLOR sta COLUPF lda (FrostyImagePtr+.SEC*2),y and (FrostyMaskPtr+.SEC*2),y ... ENDM Within the game logic you'll find this at line 577: SECTION 4 SECTION 3 SECTION 2 SECTION 1 SECTION 0 Those are replaced by the macro and anything with .SEC is replaced with the value specified above: ldy Heights+4 ; load Y with height of current section lda #ICE_TOP_COLOR sta COLUPF lda (FrostyImagePtr+4*2),y and (FrostyMaskPtr+4*2),y ... ldy Heights+3 ; load Y with height of current section lda #ICE_TOP_COLOR sta COLUPF lda (FrostyImagePtr+3*2),y and (FrostyMaskPtr+3*2),y ... ldy Heights+2 ; load Y with height of current section lda #ICE_TOP_COLOR sta COLUPF lda (FrostyImagePtr+2*2),y and (FrostyMaskPtr+2*2),y ... ldy Heights+1 ; load Y with height of current section lda #ICE_TOP_COLOR sta COLUPF lda (FrostyImagePtr+1*2),y and (FrostyMaskPtr+1*2),y ... ldy Heights+0 ; load Y with height of current section lda #ICE_TOP_COLOR sta COLUPF lda (FrostyImagePtr+0*2),y and (FrostyMaskPtr+0*2),y ... Having a separate kernel loop for each section is we have all those Frosty Pointers. Quote Link to comment Share on other sites More sharing options...
vidak Posted December 3, 2017 Author Share Posted December 3, 2017 Thank you very much! I have one last question - what is the significance of .SEC*2 in loading the pointers in the kernel? Is that because the pointers are 2 bytes? I owe you a beer or something! Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 3, 2017 Share Posted December 3, 2017 You're welcome. Exactly, because the pointers are 2 bytes. Quote Link to comment Share on other sites More sharing options...
vidak Posted December 5, 2017 Author Share Posted December 5, 2017 I'm having a little trouble understanding how to set pointers.I can't seem to draw the right image on the screen. Basically what I want to do is draw a little multi-coloured sprite at coordinates 40, 80. I was using SET_POINTER Player0Ptr, Guerrill0 before, but that was drawing all $FFFFFFFF for the height of the character. I set the pointers just before the Main Loop, and I put the pointer reference in the Over Scan. Could someone help me? How do you set up pointers?I know they're not necessary for this stage of experimentation and learning, I could use LDA Absolute,X - but at some point I will have to learn how to use pointers. Please see the source code. coloured_guerrilla005.asm Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted December 5, 2017 Share Posted December 5, 2017 I was able to debug this using the following steps. Hope this helps. Search for GRP0 and then trace it back to the lda (Player0Ptr),y instruction. Look at where Plater0Ptr is being set lda ShapePtrLow sta Player0Ptr lda ShapePtrHi sta Player0Ptr+1 Look at what sets ShapePtr ShapePtrLow: .byte <(Guerrilla0 - PF_HEIGHT + 80) ShapePtrHi: .byte >(Guerrilla0 - PF_HEIGHT + 80) Build the project and take note of the following label addresses: Guerrilla0 f0d3Player0Ptr 86 Player0Clr 8f Run the game and set a breakpoint on the indexed load ~ break DoDrawGrp0 ~ Look at the values of each pointer and Y register to determine where the load is pointing to and compare it with where it should be pointing to Player0Ptr 86 = f105Player0Clr 8f = 0000 <- not initialized Realize the color pointer was never initialized. Review the code to see why. Found copy paste error. lda ShapePtrLow sta Player0Ptr lda ShapePtrHi sta Player0Ptr+1 lda ColourPtrLow sta Player0Ptr <- storing to the wrong variable, now both pointers are wrong lda ColourPtrHi sta Player0Ptr+1 <- storing to the wrong variable, now both pointers are wrong Fix copy paste error, build, set breakpoint again, run until breakpoint is hit. Pointers look better: Player0Ptr 86 = f0ecPlayer0Clr 8f = f105 Y = 8A Compute the indexed load target address: (Player0Ptr),y = f0ec + 8a = f176 This is much higher than it should be. Guerrilla0=f0d3 and we should be loading P0_HEIGHT=25 past that or f0ec. Hey! f0ec is the ptr value before we added Y offset. Change pointer to account for Y offset. Y starts at PF_HEIGHT and decreases as the screen is drawn by the player offset. So we need to subtract the PF_HEIGHT from the Guerrilla0 label and then add back the player's vertical offset. In this case it's simply hardcoded to $80, but once you start moving the player you'll need to set the pointer correctly by recalculating with the new offset. ShapePtrLow: .byte <(Guerrilla0 - PF_HEIGHT + 80) ShapePtrHi: .byte >(Guerrilla0 - PF_HEIGHT + 80) ColourPtrLow: .byte <(GuerrillaClr0 - PF_HEIGHT + 80) ColourPtrHi: .byte >(GuerrillaClr0 - PF_HEIGHT + 80) Quote Link to comment Share on other sites More sharing options...
vidak Posted December 5, 2017 Author Share Posted December 5, 2017 I am learning an insane amount right now. Thank you SO much. I will eventually think of a way to repay all this kindness. Quote Link to comment Share on other sites More sharing options...
vidak Posted December 5, 2017 Author Share Posted December 5, 2017 Forgive me again, I'm stuck. I noticed the pointers were loading data from memory locations that were 1 or 2 addresses too far in memory. So I changed LDA #P0_HEIGHT to LDA #P0_HEIGHT-2. This seems to load the graphics from the correct starting memory address, but for some reason the kernel only loads 24 out of the 25 lines of graphics. What am I doing wrong? Am I decrementing the scanline counter improperly? Or are the pointers not set up properly? For some reason SpiceWare has his pointers for Collect set up like this: Player0Ptr = Label + P0_HEIGHT - 1 - Y position Would that be a better method?I'm inching closer and closer to understanding how all this works... coloured_guerrilla006.asm Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted December 5, 2017 Share Posted December 5, 2017 For some reason SpiceWare has his pointers for Collect set up like this: Player0Ptr = Label + P0_HEIGHT - 1 - Y position Would that be a better method? Probably. SpiceWare was very careful to make the Collect code serve as an example of the right way to do things. Make sure you keep in mind that the graphics are stored backwards vertically and it's 0 indexed. This is why P0_HEIGHT is added and 1 is subtracted. The -1 accounts for the fact that the Label is already pointing to the first byte of data and if you add P0_HEIGHT to that you end up pointing at the byte just after the last byte of data. Finally the Y position is subtracted because the y register is used to index into the array, but that y register is also used to track the full 192 lines of screen height. So subtracting Y position allows this to work when the player is moved vertically without having to waste another register or variable to keep track of the player graphics/color index. 1 Quote Link to comment Share on other sites More sharing options...
vidak Posted December 5, 2017 Author Share Posted December 5, 2017 Thanks I'm gonna work more on this tomorrow... Quote Link to comment Share on other sites More sharing options...
zilog_z80a Posted December 5, 2017 Share Posted December 5, 2017 http://atariage.com/forums/blog/blog-148/cat-226-stay-frosty i was not an active member of this forum in that years, i think that i'm here since 2011 but had to leave any dream about atari programming by personal issues and now i'm doing my first steps since february. SpiceWare TY 1000 TIMES FOR THIS DEVELOPMENT AND DOCUMENTATION Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 5, 2017 Share Posted December 5, 2017 SpiceWare TY 1000 TIMES FOR THIS DEVELOPMENT AND DOCUMENTATION Your welcome! Do note that Stay Frosty was developed under a tight schedule, so is not well documented and thus is not the best starting point for learning - I only pointed it out to vidak as he was asking how to implement bands/sections/zones for reusing players. As such, you'll be better off looking at my tutorial Collect, which covers writing a 2K game from scratch. Because it's a tutorial, I put way more comments in the source than I normally do, so be sure to download and read the source for each step. If you have an questions just post them as a comments for step you're on. 1 Quote Link to comment Share on other sites More sharing options...
zilog_z80a Posted December 5, 2017 Share Posted December 5, 2017 (edited) Your welcome! Do note that Stay Frosty was developed under a tight schedule, so is not well documented and thus is not the best starting point for learning - I only pointed it out to vidak as he was asking how to implement bands/sections/zones for reusing players. As such, you'll be better off looking at my tutorial Collect, which covers writing a 2K game from scratch. Because it's a tutorial, I put way more comments in the source than I normally do, so be sure to download and read the source for each step. If you have an questions just post them as a comments for step you're on. yes, i`m into a "debugger époque" trying to understand there what i don't fully understand in some source code. once i will have learned a little more things... for sure Collect will be the next step. ty again!! cheers!! Edited December 5, 2017 by zilog_z80a Quote Link to comment Share on other sites More sharing options...
vidak Posted December 6, 2017 Author Share Posted December 6, 2017 Well, this is a huge step forward for me - I managed to set the pointers completely correctly in order to display a multi-coloured Che Guevara on the screen. I got there through sheer trial-and-error. It turns out the pointer needs to be set like this: LABEL - (Playfield Height) - 1 + (Y Position) - 1 Which works out to this: LABEL - 192 - 1 + 80 - 1 Anyway here is a screenshot of my progress, and here is my source code. Thank you so much to everyone who is teaching me the skills to figure out how to solve problems on my own. coloured_guerrilla006.asm Quote Link to comment Share on other sites More sharing options...
vidak Posted December 6, 2017 Author Share Posted December 6, 2017 Here are the graphics for Che moving vertically.I have the graphics for horizontal movement but I forgot to take a screenshot. 1 Quote Link to comment Share on other sites More sharing options...
vidak Posted December 6, 2017 Author Share Posted December 6, 2017 For those wanting to follow along, these files contain the horizontal and vertical graphics data for the Che character. I think I may be able to reduce the amount of ROM needed by reflecting the first frame of the up and down graphics respectively. Vertical_Graphics.asm Horizontal_Graphics.asm 1 Quote Link to comment Share on other sites More sharing options...
zilog_z80a Posted December 6, 2017 Share Posted December 6, 2017 For those wanting to follow along, these files contain the horizontal and vertical graphics data for the Che character. I think I may be able to reduce the amount of ROM needed by reflecting the first frame of the up and down graphics respectively. nice!! ty! Quote Link to comment Share on other sites More sharing options...
vidak Posted December 9, 2017 Author Share Posted December 9, 2017 (edited) I have put some more work in over the last few days! Please find the current version of the source code attached. I am currently at around 1KB. Changing the Main Game Mechanics I am going to change the main mechanic of the game from "snake with guns" to what a friend has labelled "lock and load". The reason for this change is not because I don't think I could have been able to make a kernel for "snake with guns", but because I liked the "lock and load" game so much better. This is how "lock and load" works: It's like scissors, paper, rock, except the three actions you can perform are: LOAD, BLOCK, and SHOOT. The game is normally played with two people on the bus, or on a park bench etc. You don't need any equipment at all. The point of the game is to shoot your opponent. However, before you do the SHOOT action, you must LOAD. You normally slap your knees twice in between rounds. So playing a couple of rounds would be like this: SLAP-SLAP LOAD SLAP-SLAP SHOOT In the game I have been taught, you can LOAD as many times as you like. However if you play LOAD, and your friend plays SHOOT, you lose. The idea is to LOAD while they are LOADING or BLOCKING. If you BLOCK, you will always defend yourself from a SHOOT. However if you always BLOCK, no-one will ever win, especially not you. The idea is to catch your opponent out LOADING while you shoot them. It turns out that this game mechanic can be very easily inserted into the current kernel I am writing. I will draw several Batista soldiers on one side of the screen, and several Guerrillas on the other, and the point of the game will be to instruct each of your guerrillas to either LOAD, BLOCK or SHOOT, and a simple AI will control the soldiers. The point of this part of the game will be to defeat the Batista soldiers. Stable Screen I am currently drawing around 257-259 lines. This is not the proper 262. I need to fix this. Movement and Animation This part of the game I need a little help with. I am able to get a little Che to move around the screen, but: I cannot seem to set the limits of the current screen properly - i.e. the bottom of the screen I have set does not actually appear to the bottom of the screen I want to display one frame of movement every 10 screen frames, but the 10-frame delay routine I have written doesn't seem to work properly. It is especially bad when you hold the controller diagonally.What I want to do is: (a) move Che every frame, but (b) display a new frame of movement every 10 screen frames.Currently my code allows Che to move, but the animation isn't working at all. Would it be alright if someone took a look? Any suggestions about how to cycle the animation every 10 frames IF Player0 is moving? Perhaps what I could do is increment a frame counter and then divide it by 10...Anyway it's the end of the day here, I just wanted to put this up to show this project is still alive. coloured_guerrilla007.asm seventhversion.bin Edited December 9, 2017 by vidak 1 Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 9, 2017 Share Posted December 9, 2017 Haven't looked at the code, but if you are OK with animation every 8 frames instead of 10, you can take your frame counter (if you have one) and do an AND and SHIFT to control the animation frame. This would only work if the height of the graphics and number of animation frames are powers of two, but it is probably the easiest way. Quote Link to comment Share on other sites More sharing options...
vidak Posted December 10, 2017 Author Share Posted December 10, 2017 My graphics are 25 pixels tall, and I really like the current way they look, so I'm not sure your method is going to work... Thank you so much for your help anyway. It's always reassuring to get a reply hahahah The frame counter I am using is a local one, within a subroutine. It is called "AnimFrameCounter". Should I be using a global frame counter, and only updating the animation frames ever 10 frames of that counter? Maybe that would work... I suppose what one should always do is check and see what's happening in the Stella Debugger. Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 10, 2017 Share Posted December 10, 2017 (edited) Should I be using a global frame counter, and only updating the animation frames ever 10 frames of that counter? Maybe that would work... That's the way I have been doing it, using 1 byte of RAM as a frame counter, and incrementing it each frame, so after 255 it wraps to 0. The disadvantage is that it only works properly with an animation where the number of frames is a power of 2. Otherwise you could switch to BCD mode when you increment the frame counter, ignore the right (low) nybble, and use the left (high) nybble to control the animation frame. This would give you a maximum of 10 animation frames, unless you used more RAM. If your animation is shorter than 10 frames, you would check the value of the frame counter after it is incremented and reset it when neccesary. One thing about using this method is that the duration inital frame is not always the same, and almost never the full length, but after that it would work fine. You could fix this issue by resetting the frame counter when the animation is triggered. Edited December 10, 2017 by JeremiahK Quote Link to comment Share on other sites More sharing options...
vidak Posted December 10, 2017 Author Share Posted December 10, 2017 Okay! That gives me some ideas. I have made some progress in the meantime. I will put my improvements here just in case they help someone. I have a counter for each direction of animation. What is meant to happen is when you move the joystick, the frame delay counter increments every frame. When the frame counter reaches 9 (0-9, so ten increments), it will increment the frame of animation that is meant to be displayed. The frame of animation is then stored into a global animation index, which then points to the animation frame in ROM. However I was not saving that global animation index properly: AnimateUpYes: inc AnimateUp0 AnimateUpNo: lda AnimateUp0 and #3 sta AnimateUp0 sta Animation0 clc adc #7 jmp SaveFrame This is how the code is fixed: AnimateUpYes: inc AnimateUp0 AnimateUpNo: lda AnimateUp0 and #3 sta AnimateUp0 clc adc #7 sta Animation0 jmp SaveFrame The second big mistake I made was calling a subroutine like this: bne AnimationDelay ... Animation Delay: ... rts Which was causing the subroutine to exit all the way back into the Vertical Blank subroutine calls. So now, when you move the joystick, the first frame from the correct table in ROM shows moving in the right direction, but there is no animation. All of this was discovered by using the Stella Debugger. It is very, very useful. I'd say anyone starting out making games should always look at the way their code is running in the Stella Debugger. I'd even say it might be worthwhile writing an interpreter for ASM files, so you don't have to get confused about the loss of labels and variable names. coloured_guerrilla008.asm guerrilla8_5.bin Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.