Jump to content

JeremiahK

Members
  • Content Count

    253
  • Joined

  • Last visited

Everything posted by JeremiahK

  1. Not my favorite illegal opcode! 😫
  2. Late to the party, but this is some elegant coding right here!
  3. Nice demo! I always love your work! 512 bytes is always fun to do. I have yet to do a larger demo, myself, but the smaller ones are easy to manage, while still being big enough to do an effect well.
  4. Excellent! Thank you stephana. I had thought it was some sort of bug in my code, because I think it had worked in an earlier version awhile back.
  5. Yes, INTIM is what you are looking for. It's not located in the zeropage, and none of the registers for setting the timer are either, so even after clearing the zeropage, it is still unknown.
  6. It's been a long time... This week is my vacation from work, my first since getting my job almost 18 months ago. I have been slowly working on this project when I have the chance, but I am going to be spending a lot of time on it this week. I didn't feel the need to post an update until now. I have finished the music engine for the game, as well as the intro music. I took a lot of time to make sure the tempo was correct, and it works in both 50Hz and 60Hz. Holding Game Reset on startup will force 50Hz mode, and the COLOR/BW switch selects the color palette. This will allow for both PAL50 and PAL60. (I cut the size to 4K for this demo, so if you press Game Select, it restarts. Stella doesn't seem to be auto-detecting PAL properly, but the timing works on a real system.) I only need minor tweaks from here, such as syncing the animation to the music. And allowing to mute the sound with the difficulty switches. The plan is to have the animated stars scrolling past until you press fire, which is when the game detects if you are using a joystick or paddle. Initially, the game title will be displayed above the cat, and after a game is played, score information will be displayed instead. Below the cat will be a scrolling menu, with 3 lines visible at a time. I have already finished the code for displaying the text, I just need to make it do what I want... 😎 nyancat.bin
  7. Posting this here in a new thread. I saw the topic of RAM management mentioned in another thread, but I didn't want to hijack it. Obviously there are many ways to skin a cat, to each their own. I wanted to share how I like to do it. I would love to hear how the rest of you do this, as well. For my projects, RAM typically falls into 1 of 3 categories, global, local, or temporary: Global RAM: Exactly what it sounds like. This is everything that needs to be accessible throughout the project. Your global frame counter should be here, current score, high score, etc. Local RAM: These are variables that are specific to a particular game mode, display kernel, menu, etc. They only need to be used in one area of code, and they can be recycled elsewhere. Temporary RAM: Technically, this shouldn't normally be needed. Each set of local variables should probably define their own temporary variables. But if you want to create subroutines that can be accessed from multiple areas, for example, a text display kernel, it may be best to define a space in RAM that is known to be available, regardless of the current local variables. The way I implement this is by defining each section of RAM in a separate file, for organization. First, I define all the global variables: filename: ram_global.asm RamGlobal ; start of global RAM Frame ds 1 Variation ds 1 Score ds 6 Rand16 ds 2 RamLocal ; start of local RAM Next, I define local variables in separate files: filename: ram_game.asm RORG RamLocal ; reset RAM position to local RAM SomePointer ds 2 PlayerColor ds 1 BallPosX ds 1 BallPosY ds 1 Temp ds 1 And I tie it all together in another file: filename: variables.asm SEG.U VARS ; create a segment of labels that isn't output into the binary RORG $80 include ram_global.asm include ram_menu.asm include ram_game.asm include ram_credits.asm include ram_temp.asm
  8. My thoughts exactly, would love to see what others are using
  9. Here is a slightly modified version of the routine, I was using an extra temp variable before. This version uses 32 bytes of RAM, the earlier one used 33. 8_char_routine.asm
  10. While planning my Nyan Cat game, I decided I wanted the main menu to allow up to 8 characters per line. This could easily be done with each word hard coded into the ROM, but I wanted to allow each character to be set on-the-fly. This takes less ROM when a lot of messages are needed, but it also allows this kernel to be used for 8-digit scores, if desired. I am considering remaking the score display for my game to utilize this. I have been working on this display for quite a while now, and I am glad to say it is finished! It uses 3 pre-shifted graphics tables for the font. I am using a font that is 7 pixels high, allowing 36 unique characters to fit in each page. This works perfectly for me, as I am using 10 numbers, plus 25 letters (letter-O is shared with zero), plus a space, but this could be adjusted as necessary. If this was only used as a score display, all 3 graphics tables would easily fit within a single page. The kernel and pre-kernel subroutines take up a total of 235 bytes. I split them into 2 separate routines so that I could more easily utilize them in different areas of my game, but there is no reason why they couldn't be combined. 32 bytes of RAM are used in this routine, 8 for pointers, 21 for graphics buffers, and 3 for temp variables. The graphics tables are all upside-down. Any bits not used are cleared. XXXXX___ Table #0 has the data shifted to the far left. XXX___XX Table #1 has the first 2 bits shifted to the far right, and the last 3 bits shifted to the far left (so it "wraps" around the end of the byte to the beginning). __XXXXX_ Table #2 has the data shifted almost all the way to the right. Edit: As-is, the code looks for a label FontGfx0, which would be Table #0. It assumes that Table #1 and #2 are in the following 2 pages. The way text is selected for the routine is by loading Y with the offset of the first of the 8 characters to display. You would set up a table as such: Table HEX ## ## ## ## ## ## ## ## HEX ## ## ## ## ## ## ## ## HEX ## ## ## ## ## ## ## ## The reason for this is that you can save some ROM by overlapping messages with each other. Edit: As-is, the code assumes this table is called FontText. Actually using these routines would look like this: sta WSYNC SLEEP 3 ldy #0 ; start with character #0 jsr CharLoad ; prepare for kernel jsr CharKernel ; draw kernel SLEEP 9 ; or change color, for example ldy #8 ; start with character #8 jsr CharLoad ; prepare for kernel jsr CharKernel ; draw kernel I have included both routines, as well as an example binary. 8_char_display.bin 8_char_routine.asm
  11. I believe that post was the original inspiration for me, then one day in the shower I figured out how to put it all together, haha. That would be interesting, although it would require a bit of ROM.
  12. Not that I know of, but I had wondered that as well. I know there was a color-test cart made that I thought simply rendered a typical test screen. After looking up the video, though, it looks a bit more complex than that. WARNING: Mute the sound!
  13. Thanks guys! I was hoping the game would be under 512 bytes, but it would have to be drastically stripped down. Doing simple things without RAM takes a lot more ROM... I would like to do a 128-byte RAM game someday. Probably as a 256-byte cart that does initialization, pushes the code to RAM, and jumps into it. The inspiration for the gameplay was taken from this video:
  14. You need to be some sort of masochist to code for the VCS, because the system is so limiting. One of its most well-known limitations is the mere 128 bytes of RAM on board. Programmers have spent ages seeing what is possible using these 1024 bits of information. So, I thought, why not limit myself to the extreme? I challenged myself to make a complete game using absolutely NONE of the on-board RAM. And I did it! It took a lot longer to actually finish than I had anticipated, but I have a fully-functional 2-player pong clone using none of the RAM, namely without addressing anything within $80-$FF or any of its mirrors, neither reading nor writing. This should work perfectly on a system with the RAM disabled or otherwise re-routed. Since I am not using RAM, I am only using the CPU registers for storing information. I can only use X and the stack pointer for storage, though, while A and Y take on more temporary roles. I used T1024T and INTIM to temporarily store data while swapping X with the SP, which is neccessary twice per frame. The SP normally holds the scores (both values from 0-10) encrypted into 7 bits, with the high bit controlling the vertical speed of the ball. The X register normally holds the vertical position of the ball (0-95), with the high bit controlling the vertical direction of the ball. X is also used to trigger "score mode", where a sound is played for about half a second before switching to "serve mode". These are simply special X values that cannot occur during a rally. The Interrupt flag is used to control the horizontal direction of the ball. Since there is no way to test the value of this flag, I am using the stack to push the CPU state to NUSIZ0. GRP0 is used for the score graphics, and since it never moves, I can use a simple collision detection against the playfield to determine what the Interrupt flag is. The ball's horizontal position is not stored, as it is moved with HMOVE. All other game mechanics are done with either checking the bounds of the data, or checking collisions between objects. If you disable different graphics objects, strange things will happen! In attract mode, the screen color cycles, and if you have the BW/COLOR switch set to COLOR, it keeps the color on game reset, otherwise it resets to black and white. This also just happens to fit within 1K of space. I could probably squeeze a few more bytes out to maybe add changeable paddle sizes using the difficulty switches, but I like it as it is. ramless_pong.bin ramless_pong.asm
  15. Exactly. Everything must be drawn at the same time, playfield, players, missiles, and ball. Some games like Asteroids drew all the asteroids on one frame, and the player on the next, only drawing one or the other. This causes flickering, which is not fun to look at, and should be avoided at all costs.
  16. Instead of using X for the line counter, you could store it in RAM. To decrement it, use DEC instead of DEX: LDA #96 STA $90 ; This is in RAM. It should be replaced with a label, so its less confusing. ; I havent seen your RAM variables, so this address might already be used somewhere else in your code. KernelLoop ; Preload Colors LDX $90 LDA Screen_1_BKColor-1,X LDY Screen_1_PFColor-1,X ; BK/PF Colors STA WSYNC STA COLUBK STY COLUPF ; Prepare X for playfield LDA $90 ; First, load A with the line counter (1-96) LSR ; This divides A by 2... TAX ; ...and then transfers the result to X (1-48) ; Draw Playfield LDA Screen_1_PF0-1,X STA PF0 LDA Screen_1_PF1-1,X STA PF1 LDA Screen_1_PF2-1,X STA PF2 ; Skip Lines STA WSYNC DEC $90 ; Decrement the line counter BNE KernelLoop RTS
  17. This will be my last post on here. If that is your final decision, I will respect it. But once again, I say that your idea is quite different than mine. The only reason why I referenced mine was because I thought it might help you to see how I coded my kernel, because it might give you ideas on how you would implement yours. This community doesn't play favorites. There aren't a lot of people writing code for 2600 games, so all projects are appreciated and encouraged. Regardless of what you decide to do, I wish you the best in your next endeavor! This forum is always open to you, and willing to help any issues you run into!
  18. I would like to clarify something. When I said I was working on a similar project, all I meant was a side-scroller with a player object that only moves up and down, and sprites that move right-to-left. In my game, there are "good items" you want to collect, and "bad items" you want to avoid. It is NOT, however, the same as your idea. I haven't even actually started on the gameplay aspect yet, it's basically just a demo for the kernel at this point. I am still figuring out what I want to do. Plus it's a Nyan-Cat themed game, so it is very different from your idea, actually. I hope I didn't scare you off with an overload of information. I wasn't sure how much you knew about the hardware, and it seems that you are still a beginner. That's perfectly fine, all of us had to start at that point. Follow the links azure posted above, and that will give you the basics. Start with something small! My first project was a super-simple bouncing-dvd-logo style mini-demo. As stated, if this just isn't your cup of tea, that's fine, but if you push yourself through the learning process, you will be able to do things you never imagined possible.
  19. The way I would do it would be setting the playfield to reflect mode and using PF1 to draw the main character, since it doesn't move left or right, only up and down. Then I could use both player objects to draw the enemies at quad size, allowing 2 enemies on screen at a time, per row. This would allow adding elements like multiple enemies with different colors, pickup items, etc. This would require changing the playfield color twice on every scanline, so the playfield could be drawn in the player's color on the left side, but the right side would be the same as the background color to make it invisible. Both missile objects would also be free, in case you wanted to add a shooting element to the game. Lots of possibilities! You could also scale down the size of the players to allow more on-screen at a time using NUSIZ to copy the players, but the playfield could not also be scaled down. I am actually working on a similar concept, but at a different scale. You can check out my project thread, if you are interested. I haven't posted in awhile, but have been doing some work in it lately. Also, when you post a large piece of code (50+ lines or so), it's a good idea to include it as a file.
  20. Yes, this is normal. In the snippet, it checks for the existence of NO_ILLEGAL_OPCODES: IFNCONST NO_ILLEGAL_OPCODES nop 0 ELSE bit VSYNC ENDIF This way, if you define the label NO_ILLEGAL_OPCODES, it will insert a "bit VSYNC" instruction, versus the undocumented "nop 0". And if you don't define the label, dasm warns you about it, but everything works fine.
  21. Those look pretty cool! I had to make another one, too... CLEAR asl ; 1 pha ; 1 tsx ; 1 bne CLEAR ; 2 lda #1 ; 2 sta CTRLPF ; 2 ldx #%01111110 ; 2 stx PF1 ; 2 KERNEL lsr ; 1 bcc NOEOR ; 2 eor #$D4 ; 2 NOEOR sta COLUPF ; 2 sax PF0 ; 2 sax PF2 ; 2 bne KERNEL ; 2 demo.bin
  22. Many times, I will be making graphics tables that need to be pre-shifted, or I will have multiple tables with the same graphics, some upside-down, some not, etc. If you want to make a change, you need to make sure you update all the tables correctly, and it becomes a real pain. I am sure some of you know what I am talking about... Over the holiday, I wrote a Python script that handles this for me. It inputs a single file for the graphics data and formatting options, and then generates each table to a separate file. It is very simple, with very little in terms of error checking, but it supports outputting tables forwards, backwards, inverted, upside-down, completely rearranged, you name it. GitHub: https://github.com/JeremiahK96/gen_gfx In order to use the script, create a file for the graphics table. I have included an example file on GitHub. The first character in the file is the character you want to use in the graphics tables to signify a bit that is set. After this is a number for the height of each block of graphics (sprite). So if the first line of the file is "X14", you would be using the X character in your graphics tables, and each block would be 14 bytes high. The next lines after the first one are for formatting the output files, and you can add as many as you need. Each line is 8 characters to define the layout of every byte within a table, and a '+' or '-' for standard/upside-down tables. Use 's' or 'c' to explicitly set or clear bits in the table. "sssscccc+" would output a table full of $F0 bytes. Use '7' through '0' to use data from D7 to D0 in the main graphics table. "76543210-" would output the graphics as-is in upside-down fashion, while "01234567-" would mirror it, as well. If you want to invert a bit from the graphics table, you can use the "uppercase" versions of 7-0 (%=5 inverted, &=7 inverted, etc). After the formatting options, you just need to add in the graphics data blocks, as such: __XXX___ _XX_XX__ XX___XX_ XX___XX_ XX___XX_ _XX_XX__ __XXX___ __XXX___ _XXXX___ ___XX___ ___XX___ ___XX___ ___XX___ _XXXXXX_ __XXX___ XXXXXXX_ XX___XX_ ___XXX__ __XXX___ _XXX____ XXXXXXX_ Run the script with the graphics file, and a prefix for the output files: python gen_gfx.py example.text table This outputs files as "table0.bin", "table1.bin", "table2.bin", etc. which contain the raw binary data. They can be included into an .asm file with dasm using "incbin table0.bin". Feel free to make any edits, redistribute, whatever you want!
  23. I ran into this issue with my giant nyan cat kernel. I needed to move the player objects both left and right, so early HMOVE's weren't possible.
×
×
  • Create New...