Jump to content

ZackAttack

Members
  • Content Count

    785
  • Joined

  • Last visited

Everything posted by ZackAttack

  1. Possible, yes. Easy, probably not. I think the biggest challenge would be handling the possibility that all 4 ghosts and both pacmen can end up on the same scanline. In which case you can flicker each sprite every third frame. If the AI for the ghosts is clever enough it might be possible to limit the occurrences of horizontal overlap.
  2. You forgot to change the caparison for setting d=1. You should also add a check for d=0 before setting d to 1 or 2. Otherwise the missle will change directions mid flight.
  3. Looking good! I'd like to suggest the flippers be improved so the ball reacts differently when they're moving and stationary. Right now the game practically plays itself if you just hold up. Though even that is fun to watch. I got to 155k before I got tired of holding up
  4. I don't see the != operator in the bb documentation. Have you tried using <> instead?
  5. Yes, I'm referring to this. Just use the cycle count variable to index into the array. if modFiveLookup[cycleCount]!=0 then goto FifthCycle
  6. Off the top of my head I can think of 3 options: 1) Use BCD for the variable that holds the cycle count. Then AND it with %00001111 and check if it is equal to 0 or 5. This option will use a few more CPU cycles than the other two, but is good if you absolutely must use mod 5 and don't have a lot of ROM space available. 2) Create a 45 byte lookup table with a 1 stored in every 5th byte and 0 in the rest. Then simply index into the lookup table with the cycle count variable and compare that value with 1. This option is good if you must use mod 5 and have more ROM space than CPU cycles. 3) Make it mod 4 or 8 (or any power of 2). Then you can simply AND the count variable with n-1 to obtain mod n quickly. This is the best option to use if you can tolerate using a value that is a power of 2. Ex: cycleCount AND %00000011 is equivalent to cycleCount % 4
  7. My estimate is that it would cost $15-$20 USD to construct a 1MB cartridge. Is that reasonable? I was thinking about this some more. Using $0?3e and $0?3f provides 32 locations which can be written to for bank switching. Bank sizes from 256bytes to 4K could be supported at the same time. 16-256 banks, 8-512 banks, 4-1K banks, 2-2K banks, and 1-4K bank only requires 31 of the 32 locations. This leaves one location left over to use for a meta-bank switching scheme. Though even I will admit that going past 1MB is absurd. 003e - Select 256 byte bank located at 1000-10ff ... 0f3e - Select 256 byte bank located at 1f00-1fff 003f - Select 512 byte bank located at 1000-11ff ... 073f - Select 512 byte bank located at 1e00-1fff 083f - Select 1K byte bank located at 1000-13ff ... 0b3f - Select 1K byte bank located at 1c00-1fff 0c3f - Select 2K byte bank located at 1000-17ff 0d3f - Select 2K byte bank located at 1800-1fff 0e3f - Select 4K byte bank located at 1000-1fff 0f3f - Select meta-bank. When 1MB just isn't enough
  8. I wasn't planning on support for color themes. Now that you mention it, I think it would be a good idea. Maybe I'll expand the level data so the color scheme can be controlled per tile instead of per level. That would produce a more flexible level design. You're right. That should work nicely The demo chains the addresses of the 8 kernels and the overscan routine in memory and then uses RTS to transfer control from one to the next. I think this will end up being improved in the finished game. I don't need a ski boat with a 315hp V8, but I still bought one Realistically 1MB is overkill and I could make a nice game with much less space. It's just too tempting to not do it. It's the price you pay for greatness... Seriously though, thanks for all the great advice. Now how do I convince you to do all my code reviews from now on?
  9. The Y register is used by the DRAW_PLAYER macro, so if the Y register is used anywhere else in the kernel it must be saved in memory and then restored after. In this example it shouldn't be an issue since X can be used to index into the HMP1/HMM1 lookup table and to detect when the bottom of the hill has been reached. The reads for the COLUBK could probably be immediate to save a couple cycles there. Supporting vertical scrolling also needs to be taken into account. If the hill is scrolled off the bottom of the screen it must terminate early and jump to the overscan routine. That means those remaining 16 cycles will mostly be accounted for. Decrement the variable that tracks how many lines remain to be rendered by this kernel (5) Branch out of kernel loop (3) RTS to overscan (6) Also, if the kernel performs any operation that isn't deterministic a STA WYSNC will be required to sync back up. Regarding the question of why so much memory is required. The fast macro depends on padding each sprite out to a full page. The timing of COLUBK writes will require at least 6 kernels to scroll horizontally across the entire screen. Additional code is required when the kernel is scrolled off the top of the screen because the objects must be positioned correctly for the first visible line. Lastly, it takes a lot of time to utilize the rom space as efficiently as possible. So it seems more effective to me to just waste space everywhere and get the game working sooner. It's a lot easier to increase the size of the rom than to find more free time to work on a hobby. Oh, and arranging everything in consistent sized chunks should make the tools easier to build too.
  10.  The basic idea is that P0 is always the playable character and everything else is used to create the background/level/enemies. P1, M1, BALL, and COLUBK are primarily used to draw the background in order to support smooth scrolling in all directions. I think a good example is a hill. It needs to have an upward slope on the left side, a section of level ground on the top, and a downward slope on the right. Here is a simple diagram to help explain. The top portion shows what the player will see. The bottom portion shows the locations of M1 and BALL in dark green on the left and right sides respectively. The light green and brown areas are drawn by changing COLUBK at the correct times. The wider the top of the hill is the more PF register would be needed to fill in that top light green section. Trying to update that many PF registers in a single line would be too time consuming. So to me it seems easier to just change the background color at the right time and use the objects to hide the coarseness of the background color changing.
  11. Thanks. The plan is to use more objects as needed. The sky, platforms, grass, and dirt are all placed according to level data. So they could easily be moved around in a level editor. It's probably not that noticeable in the demo, but the platforms are all different distances vertically. For technical reasons the horizontal position must be snapped to a 32 pixel boundary. The playfield probably won't get much use because it can't be scrolled smoothly. It's main use will probably be filing in some gaps on the edge of the screen. It should actually reduce some overhead for the graphics portion at least. In the demo I'm using the RTS trick that Roland suggested to string together the 8 sub kernels. This consumes 18 bytes of ram and the SP register. If I make each sub kernel use the same entry point location within the bank I should be able to just JMP directly to the next sub kernel instead of using the RTS trick. There is also some savings in the setup code because the bank switch requires a single byte store instead of storing a two byte return address on the stack. I've already started moving from the prototype to developing an actual game based. The goal is to have better animations and more complex background tiles by March.
  12. I did see that DPC+ has the windowed mode which is essentially the same thing as what I'm doing. The decision not to use DPC+ is really just my own personal preference. I wanted my first project to be limited to assembly and bank switching only. That said, I have absolutely nothing against DPC+ or the harmony cart. It's just not what I want to do for this specific project. It is a lot of wasted space, but trading huge amounts of rom space for a few cycles in the kernels is part of my overall strategy to pulling this thing off. I'm not sure what you mean by branching between kernels. But since it involves branching it is most likely out of the question. I had considered limiting the horizontal position of P0 to the left side of the screen and then updating P0 at the end of each scanline. The biggest problem with that is it gets in the way of strobing RESP registers on the right side of the screen. So keeping it as small as possible and putting it in HBlank seemed like the best choice. I posted a video of the engine prototype in action here. This was taken when it was still a 4k image. I could post the bin if anyone wanted it. The video already shows everything it can do.
  13. No, vertical position is determined by the value of Y when the rendering of the frame starts (the top SubKernel begins execution). It's 256 bytes for each sprite. The color data is only as large as the sprite. It doesn't matter what gets stored in COLUP0 when GRP0 is set to $00. So one single sprite with 4 animations and 256 vertical positions (scrolling off top and bottom) would require 1K of graphics data and up to 256 bytes of color data depending on the height of the sprite.
  14. My motivation for creating a new scheme is that I want to have the ability to swap banks as small as 256 bytes. This is the result of putting together a prototype of a graphics engine that supports 8way scrolling with 1 pixels scrolling resolution in all directions and single line kernels. The prototype fits in 4k, but that required a lot of creativity with how everything was placed in the ROM image. P0 is only drawn once per frame, but must be able to be moved around and support a different color for each row of graphic data. My solution in the prototype was to set the Y register just before scanning started according the desired P0 location and then embed the following macro in every kernel. DRAW_PLAYER_CYCLE_COUNT = 22 MAC DRAW_PLAYER LDA (PlayerColor),y ;5 Palette and Graphic data must be stored at page start (xx00) to keep this at 5 cycles always STA COLUP0 ;3 LDA (PlayerGraphic),y ;5 Ditto AND pPlayerSpriteMask,y ;4 STA GRP0 ;3 INY ;2 ENDM By putting all the P0 graphic data at the same location on the 6507 address bus I can replace the indirect addressing with absolute and do away with the mask. So having a bank size of 256 bytes allows for this macro to be used instead. DRAW_PLAYER_CYCLE_COUNT = 16 MAC DRAW_PLAYER LDA PlayerColor,y ;4 Palette and Graphic data must be stored at page start (xx00) to keep this at 5 cycles always STA COLUP0 ;3 LDA PlayerGraphic,y ;4 Ditto STA GRP0 ;3 INY ;2 ENDM This macro works by exploiting the fact that Y can't be incremented past 255. It allows for the illusion of having a contiguous section of memory with 192 bytes of padding on each side of the graphics data. 192 + 64 + 192 is clearly more than 256, but the wrap around allows the same padding to be used on both sides of the graphics data. So if you wanted the P0 sprite to be visible on scanline 10 you would set Y to 245 just before the frame starts. This causes 0 to be stored in GRP0 for the first 10 lines while Y is 245-255. On the 11th line Y is incremented to 0 thanks to the wrap around and now the actual graphics data stored at the beginning of the page is copied to GRP0. After Y is incremented past the graphics data it will once again point to the 0's in the rest of the page which effectively disables P0 again after it is drawn. A neat side effect of this approach is that all sprite graphic data is stored right side up.
  15. Page crossing is a major problem when I have an absolute indexed instruction in a kernel. The absolute address must point to the beginning of a page or the instruction will not have a deterministic execution time. I could merge the first 4 banks into a single larger bank giving 1K sized banks. One of the 256 byte banks could be RAM allowing up to 32KB of RAM. That would allow the 1MB to be divided up as follows: 4 banks merged into a single 1K bank providing room for up to 256KB of code 1 bank of RAM up to 32KB 8 banks will be used to store up to 256 subkernels. Each subkernel will be duplicated and relocated into each of the 8 banks. This will allow up to 8 subkernels to be used in a single frame in any combination. 1 bank will hold up to 256 P0 sprites. Each page will hold one sprite that is up to 64 bytes. The remainder of the page will need to be padded with $00. 1 bank will hold the corresponding color data for the P0 sprites. There will be some extra space available to use in these pages for code or data. 1 bank will hold level data Obviously this will have a lot of wasted space, but I think it's necessary to allow the kernels to meet such demanding timing constraints.
  16. So there probably won't be much interest in this then. Maybe that will change once a game gets released on it. I guess I should have mentioned that the existing schemes won't work for me because I am designing my engine to be split up into 256 byte chunks. All the existing schemes use banks that are much larger from what I can tell. I figure if everything is built to fit into a 256 byte bank that is always page aligned, there won't be any concern about throwing the timing off by crossing a page boundary. An added bonus is that is should allow me to shave a few cycles off my P0 rendering macro. It'll be so nice to gain a few cycles during H-blank. I made some modifications to stella and my codebase to support the 1MB scheme I outlined above. It seems to work ok in the emulator. Dasm made it really easy to generate a 1MB file. I'll try it out on the encore once I can find the details on how to add new banking schemes to it. So far I haven't had any luck with that.
  17. I'm creating a new banking scheme that will handle up to 1MB. My understanding of the Atari is that addresses $0X3E and $0X3F are owned by the TIA, but unused. So writing to 003E, 013E, etc. will have no effect on the system. I plan to divide the 4K ROM address space into 16 banks that are each 256 bytes in size. Each bank will have their own set of 256 pages to choose from. (16*16*256=1MB) Writing a value to 003E will select which page to map to Bank 0. Writing a value to 013E will select which page to map to Bank 1 and so on all the way up to 0F3E/Bank F. 1) Am I missing any obvious design flaws? 2) Would anyone else be interested in using this banking scheme?
  18. Is there any documentation on how to create a new bank switching scheme on the harmony encore? Does this require bios changes or is it simply creating an additional file to put on the sd card next to the rom image?
  19. I always thought the document was really good as it is now. Though I do wish it encouraged the use of aliases more. I think it would help beginners if they weren't using single letter variable names.
  20. 8 way scrolling and support for a level editor is functional. Scrolling platforms off the left and top still needs to be implemented. http://youtu.be/IBsCQDi9o9I
  21. Thanks for the info. Now I know why it was 2 pixels. Also, that link has a lot of other useful docs.
  22. The platform tile is almost complete. I'd like to get some suggestions on what colors and sprite graphics to use for the platform. It's a quad sized P1. It can be any size and the color and sprite graphic can be changed every scanline since this is a single line kernel. Here's what I have. It looks ok, but I think someone more artistic could do a lot better.
  23. Apparently I can't count. The problem was I had an extra 12 cycles in a sleep statement and that must have strobed HMOVE at a time that caused both P0 and P1 to get moved over 2 pixels to the right. Thanks for the suggestions.
  24. Does anybody have any idea what could cause P0 to be shifted over like this? HMOVE is strobed after every WSYNC and HMP0 is always $00 during all 192 scanlines. On the top portion I write to COLUP1, HMP1, and GRP1. On the bottom portion I write to COLUBK.
  25. I was thinking that ALL the code would be run on the cart. There would be an API with the bare essentials for interfacing with the 2600. That API could be emulated in a library so game development could be completely done in a modern IDE such as Visual Studio. There could also be a library of prebuilt engines similar to what batari basic offers. The benefit of this would be the ability to produce the best looking games with much less effort than writing in 6507 assembly. If the cart supports DRM you could potentially release games that can only be played on real hardware. It might encourage more homebrews to be developed if there is a way to release the game without the hassle and risk of producing a quantity of carts. There's also the benefit to players who want to purchase homebrews to play on real hardware but can't afford to pay $50 a cart. In theory an emulator could be run on the cart to allow for DRM of 6507 coded games too. Agreed. I figured this feature would be limited to new games and hacks. Anything not originally designed for online multiplayer would probably suck at it anyway. The harmony is a great product and the support for it on the forums is top notch. What if the cart could also be built as a stand alone system? Then the market for it wouldn't be limited to people that still have a working 2600. If the cart has a decent FPGA on it, both operating modes should be possible with a single hardware design.
×
×
  • Create New...