Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by NRV

  1. Yep, both methods work.. I have a lot of lines like: M0PF = $D000 ; read only GPRIOR = 623 ; shadow of PRIOR DV_DMA_ON = %00100000 in my code.. maybe if you post all of your code NRV
  2. aargh.. sorry for been late, sometimes life get in the way yep, avoiding LMS's is one of the reasons that I choose a gr.7 32 byte wide mode for my demos, only 32 cycles every 2 scan lines, compared to other modes.. well, anyways 2 extra cycles per 96 lines don't seem so bad, and for scrolling I will need those LMS's to sheddy.. about your comments: never mind! I never readed that like sarcasm (not from someone doing a Space Harrier conversion for the A8, I can tell that you know your sprites ) in the worst case I get motivated to find a better solution. Also, English is not my first language, so you need to pass all my comments through some kind of "good intentions" filter before reading them about your question I thing I'm a little lost (I should go to sleep and answer tomorrow), you are trying to init pointers for every scan line, assuming a width of 128 bytes for every line? I don't know if I'm answering your problem (give me more info, I like this kind of problems ), but I probably will try to init at least one pointer every 256 bytes and the others continuosly after the first one, like this: ldx zp ldy zp+1 inx stx zp+2 sty zp+3 inx stx zp+4 sty zp+5 inx stx zp+6 sty zp+7 ... ; alternate use of iny, inx and dex should let me init all the pointers, and when I need to draw I would do something like this: ldy #0 lda #sprite_data1 sta (zp), y lda #sprite_data2 sta (zp+2), y lda #sprite_data3 sta (zp+4), y lda #sprite_data4 sta (zp+6), y ldy #4 lda #sprite_data5 sta (zp), y lda #sprite_data6 sta (zp+2), y lda #sprite_data7 sta (zp+4), y lda #sprite_data8 sta (zp+6), y I suppose that a fixed example should be more clear, I don't know is this will really work, but we could try.. NRV
  3. That's a nice optimization! but you have opened that door, now we must get in (what have you done..) I thinked about using more pointers, but I was too lazy to make the cycle counting.. you are right about the 16x16 version, but not only that, the 8x8 can also be improved: Assuming your sprite has 16 bytes, your unrolled code will have 16 "ldy #", and every time you add a new pointer you eliminate the half of the "ldy #" still present in the code. With that you save 2 cycles and 2 bytes for every "ldy #" eliminated. But you also add the 8 cycles and 5 bytes (approx.) of the new pointer initialization. Balancing that for the sprite of 8x8, 16 bytes: - adding the first extra pointer: --> we save (16/2)*2 = 16 cycles, and (16/2)*2 = 16 bytes --> we add 8 cycles and 5 bytes = we have a net gain of 8 cycles and 11 bytes per sprite (useful for the 64 sprites demo!) Balancing for a sprite of 16x16, 64 bytes: - adding the first extra pointer: --> we save (64/2)*2 = 64 cycles, and (64/2)*2 = 64 bytes --> we add 8 cycles and 5 bytes - adding the second extra pointer: --> we save (32/2)*2 = 32 cycles, and (32/2)*2 = 32 bytes --> we add 8 cycles and 5 bytes - adding the third extra pointer: --> we save (16/2)*2 = 16 cycles, and (16/2)*2 = 16 bytes --> we add 8 cycles and 5 bytes = we have a net gain of 88 cycles and 97 bytes per sprite (we also eliminate the "inc zp+1" that was in the middle of my code, that's an extra saving) (if we add another pointer we will only save some bytes, but we will complicate the code too much) by the way (for the 16x16 sprite) I could distribute the 4 pointers in this way: pointer1 = top left byte offset pointer2 = pointer1 + 256 pointer3 = pointer1 + 1 pointer4 = pointer1 + 256 + 1 or this other way: pointer1 = top left byte offset pointer2 = pointer1 + 256 pointer3 = pointer1 + 2 pointer4 = pointer1 + 256 + 2 please get out of your corner (and throw rocks at mine, now ) Two things that I would like to ask you: - what do you mean with the "fully strip sprite route" (using a char screen?) - what is really the advantage of using screen lines of 256 bytes? wouldn't you fill the memory too fast? (I think that for a sidescroller I will use the first 64 bytes of a line for the screen 1 buffer, the next 64 bytes for the screen 2 buffer, and the next 64 bytes for the restoration screen buffer, the last 64 bytes I don't know what I would put there.. maybe interleaving some code or other data ) Could you elaborate further? Thanks NRV
  4. Hi, many thanks for all your words about the unrolled code: LDA (screen_pointer),Y STA save_area + <iteration>; 0,1,2... AND # <mask> ORA # <sprite_data> STA (screen_pointer),Y INY my code for masked sprites is almost the same: LDY #[row_byte + line * 32] LDA (screen_pointer),Y AND # <mask> ORA # <sprite_data> STA (screen_pointer),Y for every byte of the sprite. I don't use the "save_area" that you mention (I suppose that is for later restoring the background or erasing the sprite), because I have a clean background buffer that I use to erase the sprites (only in the demo5b). Your method is more memory "friendly" and seems to be more general. Also because my lines are of 32 bytes of width, "Y" goes from 0 to 31 for the first line, 32 to 63 for the second, until the eighth line, after which we do only one "INC screen_pointer+1", and "Y" goes back to the 0-31 range (obviously you could use this trick with any line whose width is a power of 2). But starting with the demo3 I made an optimization to the sprite draw routines macros, so the code for every sprite byte now looks like this: .if [[mask_x0_y0] = 0] ldy #0 lda #[sprite_data_x0_y0] sta (m_ptrScreen1),y .elseif [[mask_x0_y0] < $FF] ldy #0 lda (m_ptrScreen1),y and #[mask_x0_y0] ora #[sprite_data_x0_y0] sta (m_ptrScreen1),y .endif Thanks to the "magic" of macros, now you have 3 options for every byte of the sprite: - if the byte mask is $FF then you don't create any code for that byte! - if the byte mask is $00 then you don't need to do any masking because you are going to replace all the byte anyways! - in any other case you go with the normal routine you can see this like a kind of compression of the sprite. It helps more with bigger sprites and basically you use the masked version to draw the borders of a sprite, and the unmasked one to draw the inside of the sprite. (there is an extra optimization that you could add, if you use the unmasked code for two equal and consecutive bytes, then you could omit the "lda #[sprite_data_x0_y0]" after the first time.. but that would be easier to do if you have a tool that generates the pre compiled sprite code automatically, from a bitmap file) With this every sprite byte can cost you 0, 9 or 16 cycles, and 0, 6 or 10 bytes of code (because of this last optimization I couldn't use "iny" to save one more byte, but an automatic tool also could do it... hmm) Other big optimization that you can use is what I call the "wave" version of the code: if you know you are drawing a lot of sprites with the same frame (and I mean the same rotation), then you could draw groups of sprites like this: .if [[mask_x0_y0] = 0] ldy #0 lda #[sprite_data_x0_y0] sta (m_ptrScreen1),y sta (m_ptrScreen2),y sta (m_ptrScreen3),y sta (m_ptrScreen4),y .elseif [[mask_x0_y0] < $FF] ldy #0 lda (m_ptrScreen1),y and #[mask_x0_y0] ora #[sprite_data_x0_y0] sta (m_ptrScreen1),y lda (m_ptrScreen2),y and #[mask_x0_y0] ora #[sprite_data_x0_y0] sta (m_ptrScreen2),y lda (m_ptrScreen3),y and #[mask_x0_y0] ora #[sprite_data_x0_y0] sta (m_ptrScreen3),y lda (m_ptrScreen4),y and #[mask_x0_y0] ora #[sprite_data_x0_y0] sta (m_ptrScreen4),y .endif this is to draw 4 equal sprites for example. Sorry about the macros, I try to not nest them, but as the code evolved and the size of the sprites grow, I also get tired of the cut/paste For what's next all depends on how much time I have available, I was thinking in adding scrolling and more color through the use of P/M and DLI's, maybe for a fast vertical shooter or a side scroller. Is good to know that there is people with talent that can take requests for graphics and music (like Adam Tierney and Kjmann) The other thing that I know that I need, is a good pc-oriented graphic tool, to mix screen, characters, level data, P/M editing, animation, color editing, all specific to the A8 (but configurable), and with a simple way to export usable data (like precompiled sprites code!). I have wanted to do something like this for sometime, and open source the code so the community can make improvements. Greets to all! NRV
  5. Hi, I've been working on software sprites for some weeks and wanted to share the results. I made this just for fun and to learn and test some software sprites techniques, to see how fast I could made an "engine" that only use these type of sprites. My primary motivation was to see if a could make some routines near as fast as the "theoretical" limits to move memory in a 6502, using pre compiled sprites, unrolled code and some clever optimizations (see the code and the "technical doc" for more details). Obviously, the methods are optimized for speed, and normally use a lot of memory, but this is fine with me because I'm not trying to put them on a catridge . Instead I'm happy with having maybe just one level of a game in memory at any time. I choosed gr.7 with a narrow field (32 bytes of width) because you can still make sprites that look good for games (like with zybex or draconus), and also because you get more machine cycles per frame than in other modes (23024 to be "very" exact, assuming that the players are activated), and for fast moving objects you don't notice the loss in resolution too much. I worked in NTSC primarily (you have many more cycles per frame in PAL, but the transition is easier from NTSC to PAL.. anyway maybe I should just program for PAL). You can see how many of the frame is free, holding down any of the CONSOL keys (START, OPTION or SELECT) in any of the demos (the lower part between the two lines is the "free" part). All is programmer's art made by me, and I don't added colors by any normal method (like P/M's or DLI's) because I was concentrated in the programming techniques, so don't criticize the "art" All demos run at 60 frames per seconds, and some of them still have room for more sprites (you can think of that as time for the game logic and the music code, specially in PAL).. I was too lazy to do something more complicated than sinus tables for the movements, sorry for that (feel free to modify the code) All the code is included, you must compile it with the MADS assembler, or just move the .obx executables over the emulator.. (select the NTSC option in "Video System" the first time, to see them at my "intended" speed). I'm still playing with the code and there is still room for improvement, so maybe I will post an update in some days. Greetings to the Atariware forum, all AtariAge and the people in the "8-bit Computer Poll" post, in the Retro Gamer forum (most of them) NRV soft_sprites.zip
  6. until that you post it http://www.atariware.cl/foro/viewtopic.php?p=9707#9707 greets NRV (and yes.. post the code!)
  7. you mean changing the memory bank in the middle of a scan line?? that sounds like a good idea, I would like to know how a real atari and the emulator handle that case.. well you left out all the 64k users, but it sounds like an interesting technique, with a lot of practical uses.. NRV
  8. Hi Some months ago, I made some tests changing P/M values across the same scan line and, like Rybags says, moving up or down is basically "brute" force, and moving left or right is the hard part.. I was trying to start a simple space invaders like test game, only with P/M and a lot of cycle counting. I was using PMBASE and not the GRAFP registers and I think that I couldn't change the value of PMBASE across the same scan line (at least not in the emulator, I don't have a real Atari to test) so I couldn't change the shape of the players across the line, only the position and the colors.. does someone know if that is possible?? I didn't continue with the "game" because I ended in a lot of demos and techniques for software sprites (and the cycle counting for all the cases was making me mad ), but that is for another post.. NRV (the test basically shows 3 players "multiplexed" through the same scan lines, to use just drop first.obx over the emulator) test.zip http://madteam.atari8.info/index.php?prod=gtia2
  9. Could be useful.. http://raster.infos.cz/atari/forpc/dratex.htm NRV
  10. Hi there I recently recovered a lot of my old disks from my now dead 800XL, so it was easy to make you this atr I hope you understand the code and it can help you.. you saw the demo so, basically it have the platform logic, collisions, player movement, the bubbles shooting logic and some fast (i think) sprites routines (a lot of macros to draw sprites in 2 or 3 bytes with an offset) It was in gr.15 if I don't remember bad, and you can get some "slowdown" if you shoot a lot of bubbles from the bottom of the screen.. I don't included the sprites data, i think it was some pictures with sprites and masks and a map made in Envision for the one level.. I don't remembered all that, I just saw the code (it was after more than 10 years! I was doubting it was gr.15 at some point and thinking it was characters! silly me..) NRV (excuse my english, please) bub.zip
  • Create New...