Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by rje

  1. THAT might work. Better than waitvsync() anyhow.
  2. It doesn't work. By that I mean it DOES work, but C is so slow it reduces the game to a crawl. The function I tried using is called waitvsync(), strangely enough. Standard with cc65's <cbm.h>.
  3. I overlapped the sprites significantly -- 8 pixels on every edge I think. The result was absolutely horrible refresh. Today I got rid of the overlap and reverted to plain square sprites instead of ones with contoured shorelines. It looks uglier but moves MUCH MUCH smoother. The current view is only a bit more than 5 x 6 "squares". I also added a regional map view -- typing 'm' draws a 50 x 50 PETSCII map. That helps get my bearings, so to speak. I might instead just have a 20 x 20 mini-map on a corner of the normal view.
  4. I, too, wrote PSG code in BASIC -- it plays Invention No. 13 of course. Hmm maybe you're right about the timer.
  5. So I started writing BASIC on the X16 in Nov. 2019. Then I started writing C via cc65 in Nov. 2020. I've done only a tiny amount of assembly (I'd like to do more). Here are my impressions of coding on the X16. THE 6502 I understand (and feel) the pull to use a 65816, but I'm fine with the 6502. THE MEMORY MAP The memory map is fine. VERA access feels a little strangulated, but I abstract that with functions, and we can load data "directly" into VERA, which helps. I no longer fret over accessing VERA for anything except the PSG. As I mentioned, the single-byte ports feel tight, and I've written abstraction functions to manage it. A larger window might be nice, maybe. 4 bytes could point to the X,Y registers of a sprite, or a single PSG voice. 8 bytes gets a full sprite definition. THE RAM BANKS RAM banks are perfectly fine and extremely useful for storing piles of data. They're especially effective with C, where I can cast structure pointers to hunks of memory in a bank. The 8K bank size seems fine. 8K is plenty for storing chunks of string data (like instructions or lists). Multibank maps require simple math hidden in a macro or short function to swap through banks. The one place that a bank memory manager would be useful would be if I'm storing a heap or hashtable in banked RAM, and if I'm tokenizing and parsing input into banks for temporary storage. In those cases, I think fiddling with banks is kind of bothersome. SPRITES Sprites are reasonably easy to handle -- especially with a light library that wraps the registers used. The tricky part (for me) is creating the sprites which fit the palette and bit depth. One person helpfully wrote a Python script which converts a PNG to a C-style array of bytes. I've written a Perl script which uses that script and actually generates the loadable binary. PSG The PSG is almost beyond my ability right now. I think the lack of ADSR envelopes is (mostly) the reason. I will have to adapt assembly code, such as Dusan's simple sound players, to add sound to anything I write. And I'm not ready to attempt that. BASIC BASIC 2.0 is good as a "batch" language, for orchestrating more complex tools. Its extensions (e.g. supporting hex notation) makes it even more useful for this purpose. BASIC is fast, for Commodore equipment. It's still too slow for arcade-style games. BASIC's speed and power is fine for rogue-like games. I think simple versions of Ultima IV-like games *could* be done with BASIC and a few assembly routines. And some patience and carefulness. BASIC 2.0 is most effective for programs that are 8K or smaller. As your code grows past 8K, the mental load on its limited variable space and near-nonexistent structure makes it not worth your time. I find it significant that BASIC thrived in the 1980s with machines limited to 4K-16K of RAM. BASIC 2.0 is not very fun to program in. Very early on I wrote a Perl script that lets me write in a slightly better "BASIC" on my Mac, and transpiles down to BASIC 2.0. Essentially I stopped programming in actual BASIC 2.0 within a couple of months. C C is effective for writing code that fills up "main RAM". It's expressive enough and seems parsimonious enough to allow sane usage of memory. Pointers to structures are really a great way to use banked RAM.
  6. Oh, I really like the automatic speed adjustment. That would be super-useful for our relatively higher-tech world, where an extra ACK is a worthwhile tradeoff for high speeds. I also like "elegant". And symmetric. And cheap. And easy. So two signal lines, like ATN and DAT kinda. When one wants to send to the other, it pulls the ATN low. The other calculator acknowledges by pulling DAT low. That's the handshake?! Packets... one byte for the protocol ID (calculator version), one byte for packet type, two bytes for message length, the message, and then a checksum. Elegant. I even like the connector... I mean you could use an RCA jack for the I/O port for goodness' sake. *** So let's see... how does that work... I suppose I have to assume that delays are not in DETECTING SIGNALS, but rather in marshaling the data. That removes one variable: the time needed to present a bit to the receiver. (If I'm wrong, then I don't know what to do.) I'll go look up two-line protocols now...
  7. Works for me. Great White North Texas?
  8. The world is remote, so welcome aboard!
  9. It's waaaaaay to early to form user groups. It's not even a product. But I'm never held back by unreason, nor the lack of good sense, so I declare the NTCX16UG to be a thing.
  10. Welcome also. These retro machines are fun to muse over.
  11. I have code that can set up a voice -- that's the easy part. What I lack is the thing that "curates" the sound through an envelope in a "fire and forget" manner. The ADSR manager is the piece that requires working off of an interrupt to "curate" a played note, so to speak. In my mind, it would be handled by assembly code, since as an interrupt process it should be as efficient as possible. Envelope_Manager: ; voice is in X? load status, indexed by X ...dispatch based on state... Attack: increase volume by a_ratio,x increment status if it's at max_vol and fall through else rts Decay: decrement volume by b_ratio,x increment status if it's at decay_vol and fall through else rts Sustain: increment status if sustain is done and fall through else rts Release: decrement volume by r_ratio,x turn off voice and mark done if it's at zero_volume rts
  12. OK, replaced the BASIC version with the C version. It's more responsive, but the scrolling is terrible. Also I don't like the way I did the map. I have to rethink things and use fewer sprites if possible. For example, I use sprites to tile the ocean. I shouldn't have to do that -- surely I can just use characters to represent the ocean. Like a reverse period, or something. Then, the land sprites themselves are memory hungry. Each one is 64 x 64 and 8 bit pixels -- 4K! Oink! I think I need to go back to using "coastline" sprites for the edges. 8 x 64 and 64 x 8 sprites. We'll see. And even after all that, there does appear to be an obvious redraw going on when the ship moves: the sprites appear to stagger. In other words, C is not fast enough.
  13. Sounds like he just needs a coin flip.
  14. I can see that. And that's a good simplification for an interrupt-driven envelope manager. Thanks.
  15. Here's the functions I coded up in my proof-of-concept. void runVoice( unsigned voiceNumber, Voice* voice ); void runVoiceWithEnvelope( unsigned voiceNumber, Voice* voice ); int getTunedNote( unsigned index ); void bang(unsigned frequency); Each voice has a dedicated envelope, so runVoiceWithEnvelope() can figure out the envelope's address.
  16. Using a PSG noise register thingy might be a good idea. I think the emulator doesn't have one source of randomness. That said, my "Blinkenlights" demo displays several memory locations that change state while the program runs. They include a chunk of the CPU stack ($01D5 - $01E4), which is of course NOT random, the time registers (TM_SC, TM_MI, etc etc), which are of course NOT random, and the addresses from $9F64 through $9F69 and $9FB8 through $9FBB ("external devices"), which ... well they surely can't be random.
  17. I've worked a bit more with VERA Sprites and the PSG both, and I have an update. (1) The sprite bitfields are not as big a problem as I originally thought. They are PAINFUL when programming in BASIC, but I suggest a thoughtful extension command would resolve that. When using C, the bitfields are no problem at all. (2) The PSG has one major drawback, and that is the lack of ADSR envelopes. The solution would have to be something like an interrupt-driven software ADSR system in assembly language, with a small bit of RAM set aside to manage state. The 16 bit ABI can be used to pass parameters. Now I haven't used the synthesizer chip on the X16. Maybe it's easier to use.
  18. I wrestled with the code a bit, and am feeling tired over it. I feel like it's all going in wrong directions. But that's no reason to throw it out. That just requires some careful UX thought. That's what it needs: an old-school but effective common user interface. It has a lot of menus. And I'm sorry to say they don't all work the same way. This implies that I need a common menu method that the various drivers call on to draw the user's input properly.
  19. So far, my Kernal Test only tests these: 1. CHROUT 2. MEMTOP (read and write) 3. MEMBOT (read and write) 4. SETNAM, SETLFS, LOAD (implicitly though...) 5. IOBASE 6. SETTIM and RDTIM I'm looking for more easy KERNAL tests... I'm thinking the IEC Bus is not a trivial thing to test, so maybe I can test: Channel I/O calls? STOP, GETIN, SCREEN, PLOT? Any suggestions?
  20. Yep, I was messing with those opcodes, grouping them one way and another, thinking "surely a little decode can reduce size". I'm sure Woz didn't decode because 300 bytes was the golden compromise for him.
  21. I'm still thinking that a 16K ROM bank could benefit from Sweet16... assuming that you only want to work with that 16K, and assuming you've got more stuff to put in that 16K than you would normally be able to squeeze into it.
  22. Given your suggestions about better use of SWEET16 -- i.e. as a setup rather than something for inner loops -- maybe there's not much benefit to using something like it to replace bits of the KERNAL. Except for KERNAL routines used for system initialization, of course.
  23. Ed and I were comparing original source to original "source"... turns out SWEET16 itself either has variations or typos in the wild. I get that yours is an open-source implementation of the API. It's also more likely to work for me than the original.
  24. I bought an SN76477 from Radio Shack in the 80s. I wasn't up to the challenge. But it was cool.
  • Create New...

Important Information

Please review our Terms of Use