Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


ZeroByte last won the day on July 17

ZeroByte had the most liked content!

Community Reputation

293 Excellent

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. You can use C-space variables in asm() calls with cc65. C identifiers are imported into assembly with a _ prepended to their names. So you could do this: char[12] onthefly ... asm ("lda _onthefly") This would be like &onthefly - I haven't tried things like asm("lda #<_onthefly") - not sure how sophisticated the asm() command is, but since it's part of the same software suite that is also the assembler, I imagine it's able to decipher that.... I used it in my IRQ handler asm("jmp (_systemIRQ)" where in C, systemIRQ holds the address from $314 at boot. I don't know where C put it, and don't care.
  2. I didn't do it because I needed to. I actually did it because I was lazy and because I wanted to use pointers in the hopes of not using any global variables like the sprite regs. (They ended up being global anyway for reasons). I got tired of keeping track of sprite slots and every time I'd add something or change something, I'd have to go make more #defines and I got sick of it, so I just decided to do it this way. It was very convenient while messing around, because I could literally draw anything at any time I liked w/o having to keep track of stuff. I leveraged this the most by using the scoreboard code as debug displays. I just put 4 or 5 scoreboards on the screen and loaded the "scores" with values I was interested in watching in real time. I made the scoreboard able to show hex to help with this. It was a great "code reuse" exercise. And when I don't #define debug, none of them are drawn to the screen, and I didn't have to save sprite slots for them when not in use. Also, it made the IRQ routine able to work faster by only needing to set the VERA data port once before striding straight through the sprite regs in order, without having to check anything or skip over un-altered sprites. It just writes bytes into the regs until it hits the first one that "used to be there but is gone now" and blanks them out until it reaches the first one that was already blank. When there's only one sprite on screen, it only has to consider two sprites (the one flagged FE is always going to be written as all-zeroes). Basically, if you put logic in a loop, that logic slows it down, and it can often be faster to just grunt 19*8 bytes into VERA than it would be to say "did this change? No? Did this change? No. Did this change? Yes? Let's see, that's sprite 9, so that sprite's register base is.... 0x1fc48. Okay, let's move the data port to 0x1fc48. Whew! Time to write 8 bytes." (Oh wait, you want me to think about which of those 8 bytes is changed, too?). If this code is too slow, then you can get tearing in your sprites if they're at the top of the screen. The Kernal's VSYNC routines alone will bleed dozens of lines into the display if the user is hitting several keys. (That's why priority #1 for my IRQ handler was to update the scroll register, by the way) My "multiplexer" basically guarantees that all displayed sprites' data is contiguous from sprite 0 to sprite N, after which is nothing, so it can just write them all in one swoop. Plus this flexibility was fun to play around with - I used it to make the bird be a trail of birds, for only like 3 or 4 lines of extra code. I'm not saying this is the best way to do things - it's just what I came up with. My project was more about giving myself something sufficiently complex to do that I'd learn things along the way, but not so complex that I couldn't achieve it.
  3. I'm not sure what you're trying to do with sprites, specifically, but here's how I handled them in Flappy Bird: each "object" (not in the C++ sense obviously) has an update function which writes out its current state to an array of shadow registers in main memory. Each object might use multiple sprites, and it returns a pointer to the next sprite slot once complete. So at the end of the update portion of the loop, I have an array of sprite registers in main memory. Since I wasn't using the settings in sprite reg6 (collision, layer, flip), I decided to use this as a marker in the shadow regs. The first unused sprite has FE in reg6. FF = clear sprite (i.e. wasn't on screen for the previous frame). I have an end_of_frame() function that I call at the end of the main loop, which writes FE to the "current" sprite slot and then waits for vblank(). The IRQ routine simply blits the bytes from the shadow registers into VERA. It goes until it reaches a sprite with reg6 = FE or FF. If FE, it writes all-zeros for each sprite but puts FF for reg6. It continues until it encounters an already-clear sprite (FF) or the end of the array. This essentially performs sprite multiplexing. During the game run, the bird, scoreboard, and pop-up banners are constantly being switched around between sprites, depending on the order I call their draw() functions. It's probably not the most efficient thing around, especially since it's written in C, but it works well enough, and the VBLANK() routine has next to nothing to do but mindlessly copy bytes into VERA.
  4. But I think what @StinkerB06 meant was to ask whether anything has changed regarding how you communicate with VERA… (any registers moved / changed, etc)
  5. 16-bit rotations are easily doable without loops because the bit that rotates “off” the register rotates into the carry flag, and the carry flag rotates into the register. so say you have a 16bit unsigned variable held at myword, and you want to multiply by 4. ASL myword ROL myword+1 ASL myword ROL myword+1 Do it a third time for myword * 8. ASL always shifts a zero into the LSB. ROL shifts the carry bit into the LSB. (that’s why it’s ASL on the low-order byte) so to finish your formula, after the three shifts: LDA #$10 CLC ADC myword STA myword LDA myword+1 ADC #$FC STA myword + 1 This can be done more efficiently but I wanted to use the most straightforward methodology as the example.
  6. I've been working towards a sound API - I'm still going round and round as to certain format issues / performance issues / etc. There's a very nascent version of it in my Flappy Bird game. The idea is to use a simple data stream format for the various chips, and some basic function calls to start/stop them. My biggest issue right now is getting a little bit more experienced in dealing with banked memory, as there's just no way around using HiRAM for music and PCM data. SFX streams are very short and fit just fine in LoRAM, so it's easy enough to define those in-line in C as #include'd const byte arrays... but songs tend to push the 20KB barrier (VGM-exported songs I'm messing with) on YM, and even more for PSG. Plus, there's already a simple sound engine for BASIC posted in the downloads area. Have you checked that out yet?
  7. ... or pricing concerns, or electronic concerns with how it works on the PCB, or with the clock, or one of a dozen other things. I'm sure it's not because they're going to crank it up to being a Neo Geo.
    I ran version 0.1.1 just fine in Ubuntu 20.04 - it's quite convenient, but still a little buggy and still a touch confusing at first until you get the hang of it. Granted, the first confusing thing was actually my fault - I was playing around with an "8x8" font, but it just wasn't displaying properly - it turns out that the PNG was actually quadrupling the pixels, so once I scaled it down to 1:1 resolution, everything worked as expected. I like how this program makes it very easy to see what 4bpp assets will look like on-system with various palette swaps at just the click of a radio button. Personally, I would prefer that the palette be displayed in 16 colors per row instead of 10, so each row would be a unique "palette" for 4bpp mode. I also like that the 2-byte header is optional (I'm hoping that the Kernal's LOAD/SAVE routines get updated to support "headerless" files, since you can already specify load addresses on the 'command line.')
  8. I'm sure there are lots of behind-the-scenes reasons why this hasn't happened, but would it be possible to get someone to push the "R39 = official" button on the Github repo? My R39 workarounds include doing some manual things because cc65 gets broken on R39, and there are other tool chain projects like Prog8 etc which are also in limbo until this major revision gets officially blessed. I'm intentionally keeping my tools frozen as long as R38 is the official version, and I've read posts here and elsewhere by those who are ready to merge updates into cc65, etc.
  9. Isn't there an IO address to ask the emu what version it is? Another idea might be to do something like stz $00 stz $bfff lda #1 sta $00 sta $bfff stz $00 cmp $bfff beq R39 .R38:
  10. I was always more a fan of Spirit than of Opportunity - the Gusev Crater area was just far more interesting to me than the flat plain where Opportunity landed. Spirit had to fight for every step.
  11. That's a good example of YM goodness. Not only earworms there - don't forget the marble munchers. In fact, those things and that tune go hand-in-hand for me. For me, though, the definitive sound of YM is Japanese stuff. Those composers just "got" FM in a way that many western products didn't. I recently discovered a Japanese arcade exclusive game called Xexex, by Konami. It's like Gradius and R-Type had a baby. The music is quite good. It leans pretty heavily on PCM tracks though. I ripped the YM2151 portion out of some of the VGM files for it, and played them on X16, and the music was pretty bare-bones. They pretty much used the YM as an accompanying synth in the overall tune, as opposed to the main instrument with PCM percussion.
  12. When I got my set of YM2151 chips in the mail from China, I was looking at them, wondering how long it would be before I ended up actually hooking them to anything and playing music on them. (Still haven't gotten my workspace organized enough to start such projects tho - I really need to quit being lazy). One thought I had about those chips was that when they go into a general-purpose computer like the X16, they "get to" do new things. What I mean is that all those chips that went into arcade machines ended up spending their lives playing just a few tunes and SFX that were built into whatever game they were part of. In a way, now it's like the chip gets to sing different songs instead of just that same attract mode music that they played over and over and over. I know - personifying a chip seems a bit much, but I do wonder what machines these chips used to be in and what music they used to play.
  • Create New...

Important Information

Please review our Terms of Use