Jump to content

Ed Minchau

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Ed Minchau

  1. There's another character there after the colon that's showing up as unprintable on Notepad.... looking at the data in Irfanview I see it's a 7F. The last zero is followed by a 0A, then the image starts at the top left corner.
  2. It's almost at the point that I can add the buildings.
  3. Your SETLFS needs to be set to A=01, X=08, Y=01. Is SD_DEVICE = 08?
  4. How about using tiles for the towns? Not everything needs to be a sprite.
  5. There's a big problem when trying to save data from the RAM banks: the Kernel uses bank 00 in the middle of the save operation. The solution I've been using is to always leave bank FF (3F on a 512k system) free. Then I copy 7000-8FFF into that bank, copy the bank I want to save into 7000-8FFF, save the file from that location, and then copy bank FF (or 3F) back down to 7000-8FFF.
  6. Heh. I got a new phone, and couldn't see a way to sign in here, so I figured I'd just write a test post to see if I was in fact signed in. Yup.
  7. So this was a minor triumph. Messages are stored as compressed text, with common words in a vocabulary represented by only one or two bytes. This is parsed into a buffer and then divided up into lines of text. You'll notice a couple of different fonts here. The letters UTC after the time are on two tiles on layer 1. All the other text is on layer 0. The first 64 tiles on layer 0 are letters, numbers, and punctuation. The ellipses at the bottom of the message window is tile $80, and there's six tiles for the local area name and another six for degrees latitude, degrees North, degrees South, degrees longitude, degrees East, and degrees West, and those 12 tiles are also in that $81-8F range. I've reserved 3 tiles for future use in that $80-8F range as well. That leaves tiles $40-7F for the newsfeed (currently just lorem ipsum) and $90-FF for the message window. Each of these tiles has two characters in a tiny font. This font is only 64 characters and is stored in low RAM, and I have a subroutine that takes the left character value in X, the right character value in Y, and the tile number in A, and it creates the 8 bytes for the combined tile and pushes that to the tile data in VERA. The tile map for the newsfeed is static, except for the color information. The tiles themselves are updated every time the newsfeed scrolls one character to the left. For the message window, that's 10 tiles wide and 15 tiles tall. With the scrollbar on taking up the rightmost column, that leaves 135 tiles. But, I only have 112 tiles to work with for that window. So, as each line is being displayed the tile map in that window is being updated line by line, padding with spaces on the right. Even so, it sometimes runs out of tiles for the display, hence the ellipsis tile. Clicking on the up and down arrows moves the index of the item (line number) at the top of the list to change, and the message is redrawn. I can't click and drag on the scrollbar - yet - but I think that might be possible. It isn't just a message window. That same window is also used to display a message archive (sort of like an email inbox), and the main Build window (which allows selection between Life Support, Infrastructure, and Production), and then each of the Build categories will have a list that you can scroll through and select the building you want. This window will also be used for the stock market and the local info window. There's a lot of different things that can go in there, a lot of potential mouse click hot spots, not all of which are active at once. So I had to set up all the code structure to do things like place a tile map in that window on the fly. I've also added Events and Triggers. Events are subroutines that are not executed each main loop, but are intermittent or one-time-only or delayed. For the main loop to know when to execute those events, they need to be triggered. A trigger takes one of two forms here. First is a Timer trigger. This is a four byte data structure. The first two bytes are a countdown time, decremented each time the game clock updates. The next two bytes are either the address of an event, or if the "high byte" is zero then the "low byte" is an index to a list of events. So, when the timer reaches FFFF, the associated event is pushed onto an event list and the trigger is removed from the timer trigger list. Later the main program looks at the length of the event list, and if non zero executes all the events in the list, simply calling all the addresses listed. The other type of trigger is a Flag trigger. This is a five byte structure. The first byte is a zero page address, the second is an AND mask, the third is an OR mask, and the last two bytes are again the event address or index. For this type of trigger the byte is loaded from the zero page address into the accumulator and ANDed with the AND mask. If the result is the same as the AND mask, then the zero page byte is loaded into the accumulator again and ORed with the OR mask. If the result is the same as the OR mask, then the event is put onto the event list and the trigger removed from the flag trigger list. This can be used to look at a single bit or all 8 bits of the byte. Any bit values that must be 1 are set to 1 in the AND mask, any bits that must be 0 are set to 0 in the OR mask, and any bits that are Don't Care are set to 0 in the AND mask and 1 in the OR mask. If the AND mask and the OR mask are the same, then this trigger will only fire when all 8 bits of the zero page byte are the same value as the masks. Unlike the timer triggers, the flag triggers are all checked each time the program cycles through the main loop. So I have three dynamic lists: two lists of triggers and a list of events called by these triggers. The events are just subroutines, which can themselves push other triggers onto the trigger lists. So by using the timers and flag triggers I can have events that occur some time in the future. An example of this is something I did to the cursor. It's a 4bpp sprite, and its default palette index is 1. When the mouse button is pushed now, I change the palette index to 3, making it blue. Then a flag trigger is pushed to the list, looking at the zero page value where I'm storing the value of the mouse button. Both the AND and OR mask are zero, and the event called just changes the palette index back to 1. So now, when you click the mouse it turns blue and when you release it it goes back to black and white. My next step is getting the Bulldoze working and the Build secondary menus. I've also figured out a way for the user to click anywhere on the asteroid image and the asteroid will rotate and snap to that spot; I just haven't coded that part yet, as it's about 4th on the to-do list. Bulldoze and Build shouldn't be as difficult as this window was, so my next update will a little sooner.
  8. It's probably up to the members of this group to write the code for development tools. I wrote an assembly language editor that's really a fancy Monitor program with labels, and I've been using that a lot, but most of my development for the X16 has been on spreadsheets. Other people have worked on things like sprite editors and text editors and palette editors and music sequencers, and I believe David Murray has a version of PETDRAW out for the X16. There's also a lot of c libraries being written by people here.
  9. It looks like you've got a maximum of 88 sprites for the terrain. Maybe another 16 for coastlines, and then your ship... that's a lot of sprites. I'd set aside 1kb of low RAM for all your sprite attributes. When you're making changes, say to the XY values or the VRAM location, you just do the changes in that low RAM area. Then when you're ready to change all the sprites, you just copy that whole 1kb from low RAM to 1FC00 all at once on a VSYNC, and that should stop the flickering.
  10. Some 16x16 sprites could smooth out those coastlines. If a big square is water, check each corner for the neighboring squares, if both present a little curved piece can go there. Or a 64x8 sprite can go on one edge of a water square if only one of the four neighbors is land. One horizontal 64x8 beach, one vertical 8x64 beach, and one corner piece 16x16 would really smooth out the map. Edit: there's really only 16 combinations of neighbors being land or water, so for a water tile check all four neighbors and then select the appropriate one of 16.
  11. Yep, that should be 192+48, but the palette index shouldn't matter for 8bpp. Weird. That is unless these are in fact 4bpp, in which case the palette being off by 4 does make a difference.
  12. That'll do it. Are you using the default palette?
  13. A 64x64x8bpp sprite takes 64x64 bytes of data, or 16 pages of VRAM. I think you're only giving it 8 pages.
  14. Matt already has shown an assembly language version on YouTube, 320x240 pixels took a little over twelve minutes. Of course, he wrote the code to be clear for his viewers, not the most efficient code possible. It might be possible to get it under ten minutes.
  15. Version 2 looks a lot better. Those definitions are a much better solution than before.
  16. If you're getting the sprite data from $04000 then the VERA high address bit is 0. Height and width are both 32 pixels, so the bit values for the last byte in your attribute should be 10100000. But if you're starting out with 32 instead of 2 for both, 100000 shifted left 6 times shifts it right out of the byte. Set those Height and width values to 2 instead, or shift Height only twice and leave width alone.
  17. Yeah, I'm going to finish this even if emulation is the only way to play it. And if it works on x16, then I'll be able to port it to other systems too.
  18. Oh, I'll just add some functionality to these buttons, I said. It'll just be a few chunks of code, no big deal, I said. Hah. Turns out I've had to create a whole bunch of interlocking systems of code. I've had to add the idea of Events, which are pieces of code that don't get run immediately, but await some trigger condition. Not all Events can be armed at one time, there's just too many. Instead I need to have an Active Trigger list. A trigger can be a countdown timer or some combination of AND and OR bitmasks for Flag bytes. This active trigger list is checked every time the clock display updates. If a trigger is pulled, then what follows that trigger in the list is an address in RAM of the event to take place, and that address is pushed to another list of Triggered Events, and an event handler routine later just runs all the subroutines in the Triggered Event list. So basically the "few chunks of code" I'm needing to write is actually most of the rest of the game engine. Even just putting text in that message window on the right raises the question: what text exactly? After writing out a bunch of messages and stuff for the newsfeed, it quickly became apparent that I was going to run out of room just for the text data. I've had to do some sneaky compression techniques. Some of the less-common words are spelled out, but the most common 1, 2, 3, and a few 4-character words (128 total) are represented by codes 60-BF and E0-FF, and another list of 256 (well, about 210 of these so far) words 4 or more characters long is represented by two bytes ($10 and the index of the word). I have a vocabulary list stored in VRAM that's about 2.5kb, and 768 index bytes in low RAM pointing to these 384 words in VRAM. My resulting compression ratio is about 3:1 right now, but I expect that to get better as I write more text and reuse these vocabulary words. As I've been setting all of that code up, I've also been doing a few more things like touching up some sprites and the font and adding the population display on the bottom left side of the screen. Here's what it looks like now:
  19. I do use VRAM for lookup tables already. It's particularly useful if you have a big table that needs to be read sequentially. For my Asteroid Commander game, there are 88 tiles that make up the asteroid, and for each pixel I need a radius value and an angle value. Those are stored in an 11kb table in VRAM, and are used to generate a second 11kb table in VRAM that matches a spot on the map to that pixel. The second table is read sequentially later when it's actually drawing the asteroid, using the location data and asteroid rotation to select between a daytime color and a nighttime color, pushing the result sequentially to the tiles.
  20. I downloaded pdfs of both the VIC-20 and C64 reference manuals. The VIC-20 one is particularly useful for the oldest Kernal routines, like CHROUT and GETIN and PLOT. The X16 manual only covers news stuff specific to the X16.
  21. If you're doing bit operations, I assume that section is in asm? The BBR/BBS commands come in very handy for this. Edited to add: I'm doing something like that for the row of buttons near the top of the screen in Asteroid Commander. Each one is a 4bpp sprite, and has a flag bit in a zero page byte called BUTS. The routine that draws these sprites uses the BBR commands to check the associated bit. Whether it's a 0 or 1 determines which palette offset is chosen for the sprite attribute. Similarly the subroutine that checks for mouse position won't recognize a button that has a zero flag. I've had to set aside an additional 3 bytes of zero page for flag bits on buttons in the message window, only a few of which can be active at one time.
  22. Indeed. I'm willing to lay down money right now on a built board, with things not quite right yet. I have put a LOT of hours of assembly language programming into the X-16, and the game I'm writing now absolutely requires accessing VERA exactly as it is in the documentation. I don't care much about the keyboard being flaky, as long as I can type LOAD"ACOM.PRG",8,1 RUN Seriously consider populating the Store; at least put a PayPal Donate button on there. Keep the 8 bit guy Patreon strictly for 8 bit guy, so that accounting and taxes don't become a nightmare. And I think you're far enough along in the design and testing that the issues with the keyboard and SD card can be resolved. That means that this project is ideal for a Kickstarter. It isn't vaporware. You've got the license to use the commodore Kernal, you've got tons and tons of documentation out there (much of it on youtube). You're on the third iteration of the board and almost got it. All you need is cash to offset your own costs and get the project rolling. You mentioned $100k to guarantee the project gets off the ground. Put up a kickstarter: if you get your 100k within a month of the launch, then good. If you get significantly less, you'll know it's time to reevaluate. But at least people wouldn't be voting in a poll, they'd be voting with their wallets.
  23. And a PayPal button so we can buy the merch.
  24. This website needs a store, somewhere we can buy everything you've got to offer from keyboards to t-shirts to coffee mugs to dev boards to eventually actual computers. Something prominent, with periodic updates in the forums ("now selling plush petscii robots!" etc.). At least something so we can keep the project rolling until the kickstarter is ready to go.
  • Create New...

Important Information

Please review our Terms of Use