Jump to content

rje

Members
  • Content Count

    174
  • Joined

  • Last visited

  • Days Won

    5

Everything posted by rje

  1. Welcome! You don't have to be old to be an 8-bit nerd!
  2. Namaste/namaskaram Anshul! I hope you find the X16 an enjoyable hobby. I followed Stephen Gardner's blog for quite a while, always keeping a cost/benefit tally in my head. I constantly wondered how I could justify the time and money investment in buying it. Not cheap of course, but the other problem is the time investment required to grok it well. I lack that time. The X16, on the other hand, seems comprehensible to me, and more affordable. So, while I would love to have a C65 clone on my desktop, The X16 is the winner in my own books.
  3. My space game, ever in slow-time development, uses binary data for ship data, character data, map data, and game state data. I load these into high RAM and use them as needed, pulling them into main RAM long enough for a display or whatever. Perl is really useful for creating binary files -- more useful than C, in that these sorts of tools are scripts, not worthy of dedicated development time with a proper language (like C). Here's the easiest way to create a one-record binary file. use strict; EVERY Perl script should start with that line there. That enforces some discipline in both the developer and the Perl interpreter. Now let's declare our data and shove it into Perl variables. This gives the data some tweakability, decoupled from the binary file's structure... although it also gives us an idea as to what lengths we want our data to fit into. my $header = "TEMPLE OF APSHAI GAME STATE"; # fits into 31 characters my $name = "MATT HEFFERMAN"; # fits into 15 characters my $gx = 502; # global X, looks like 2 bytes my $gy = 500; # global Y, looks like 2 bytes my $sx = 3; # local X, 1 byte my $sy = 10; # local Y, 1 byte my $life = 10; # 1 byte So we have seven pieces of data up there. Now let's write them. open my $fp, '>', 'GAMESTATE.BIN'; # fopen for writing ('>') print $fp pack 'AC', 'X', 16; # two byte throwaway 'header' print $fp pack 'A31x', $header; print $fp pack 'A15x', $name; print $fp pack 'vv', $gx, $gy; print $fp pack 'CC', $sx, $sy; print $fp pack 'C', $life; print $fp pack 'x16'; close $fp; The 'pack' command puts our data into a binary format. We specify that exact format with the string that follows each pack... that string is a template telling the command how to pack in the data. For example, pack 'A5', 'HELLO'; tells Perl to pack in 5 ASCII characters from the source string 'HELLO'. Add a zero value with 'x'. For example, pack 'A15x', $name; tells Perl to pack $name into 15 ASCII characters, then add a zero byte to the end of that. Or this line, which simply adds 16 zero bytes to the file: pack 'x16'; 'v' encodes an integer in little-endian format. 'CC' encodes two unsigned char values. And so on. The trickiest example in my code is pack 'AC', 'X', 16; which first encodes a single ASCII character ('A'), an unsigned char value (16). This is the throwaway two bytes that the X16 will ignore when you load the file to a specific address. Since I load the file to a specific address, these two bytes are completely irrelevant. Just on a whim, I put "X16" into them. The resulting binary file is exactly 73 bytes long, and looks like this: 00000000 58 10 54 45 4d 50 4c 45 20 4f 46 20 41 50 53 48 |X.TEMPLE OF APSH| 00000010 41 49 20 47 41 4d 45 20 53 54 41 54 45 20 20 20 |AI GAME STATE 00000020 20 00 4d 41 54 54 20 48 45 46 46 45 52 4d 41 4e | .MATT HEFFERMAN| 00000030 20 00 f6 01 f4 01 03 0a 0a 00 00 00 00 00 00 00 | ...............| 00000040 00 00 00 00 00 00 00 00 00 |.........|
  4. As a practical example, here's a hexdump of a character record from my game-in-development. 00000000 58 10 4a 4f 52 4e 20 20 20 20 20 20 20 20 20 20 |X.JORN | 00000010 20 00 39 38 37 36 37 38 4d 34 20 50 20 20 00 00 | .987678M4 P ..| 00000020 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.A..............| 00000030 00 00 31 30 30 30 30 30 30 31 30 30 30 30 30 30 |..10000001000000| 00000040 30 30 4b 48 41 41 4c 4f 20 20 20 20 20 20 20 20 |00KHAALO | 00000050 20 00 39 38 37 36 37 38 55 34 20 50 20 20 00 00 | .987678U4 P ..| 00000060 00 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.E..............| 00000070 00 00 30 30 30 31 30 30 30 31 30 30 30 30 30 30 |..00010001000000| 00000080 30 30 41 52 52 4c 41 4e 52 4f 55 47 48 4c 20 20 |00ARRLANROUGHL | 00000090 20 00 39 38 37 36 37 38 56 34 20 50 20 20 00 00 | .987678V4 P ..| 000000a0 00 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.P..............| 000000b0 00 00 30 31 30 30 30 30 30 31 30 30 30 30 30 30 |..01000001000000| 000000c0 30 30 54 48 52 4f 59 53 53 20 20 20 20 20 20 20 |00THROYSS | 000000d0 20 00 39 38 37 36 37 38 44 34 20 50 20 20 00 00 | .987678D4 P ..| 000000e0 00 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.S..............| 000000f0 00 00 30 30 31 30 30 30 30 31 30 30 30 30 30 30 |..00100001000000| 00000100 30 30 |00| The first two characters are throwaways that normally would indicate the target address. Because I load to a specific address, the X16 ignores them, so I code them with the codes for ASCII "X" and the decimal 16... X16, get it? This means the X16 sees this as a 256 byte file. The file itself has four records for four characters. A 15 character name with a zero at the end; a six-digit string representing the characters "personality profile" (a displayable string); a letter denoting species ("U" is human); a character denoting number of terms served in the previous career (they're all "4" here); a readied weapon and armor; a character denoting assigned position aboard a ship ("E" is engineering, for example); and sixteen digits (stringified) representing levels in sixteen skills. All of this is playable data, although what I need primarily is name, ship position, and skill level. I load this file, along with the ship data and the player's game state, like so: load "SHIP.BIN",8,1, $A000 :rem bank1 to $A3ff load "PLAYER.BIN",8,1, $A400 :rem bank1 to $A4ff load "CHARACTERS.BIN",8,1,$A500 :rem bank1 to $A5ff I get at the player data with a long series of PEEK statements. This is superior to a long series of READ statements, but I think reading from a SEQ file would be more convenient (for transfer to main RAM) but not convenient for memory management. Overloading INPUT# and GET# to treat banks as input channels would make it easy to transfer data from banks to main RAM. Thus banks become a kind of buffer to give a kind of random access to SEQ files. But it doesn't allow direct use of banked RAM.
  5. That's actually an exciting layout, Starsickle. All those views and statuses and so on... and the reverse text on the bottom... the classic greentext terminal on black... very nice.
  6. You can also give the user something to read while the map is generating: for example, a command summary, or a selection of useful tips. Something that fits on one screen. (Yeah, I know, you might have to bank THAT as well). One other option, in the spirit of "divide and conquer", is to have a separate, GALACTIC CONTROL program that generates maps, and writes them to files, and allows you to specify the "current" map. Then the main program would simply load the "current" map.
  7. Yah, there are two separate (but equal!) feature requests for BASIC commands to easily move memory between Low RAM, banked RAM, banked ROM, and Video RAM. In some ways, the separation of these memories means each is kind of like a separate device; presumably, an abstraction layer that treats them as separate devices might be part of the solution. (1) how to deal with type data, e.g. can you move memory by type? E.G. "float poke/peek", "uint poke/peek", and "string poke/peek"? (2) what are the most useful destinations for banked data? Some brand of memcpy() is useful but not enough. (3) how to avoid excessive POKE and PEEK altogether. (4) should you be able to PRINT directly from banked memory, avoiding an intermediate variable? (5) can we arrive at uniform/overloaded functions that can copy from both banked RAM and ROM and VIDEO RAM? Germane topics include the BASIC 7 command "POINTER", as well as BLOAD and BSAVE. Discussion at: https://github.com/commanderx16/x16-rom/issues/127 and https://github.com/commanderx16/x16-rom/issues/17
  8. When I was storing ship definition data in BASIC, I would store them in strings that looked like data structures (but of course weren't): rem ------------------------------------------- rem QSP + strength + cargo + alignment + name rem ------------------------------------------- dim qs$(17) qs$(0)= "S-AL222 3IMURPHY" qs$(1)= "S-AA223 5ISERPENT" qs$(2)= "J-AL222 20 ASAR" qs$(3)= "A-BS111 80 BEOWULF" qs$(4)= "A-BS121 60 MARAVA" qs$(5)= "K-BA122 6 TARKINE" qs$(6)= "Y-BS121 20 BAKAAL" qs$(7)= "P-DA643 40*AZ ALRRAK" qs$(8)= "R-DA111200 MARCH" qs$(9)= "G-DL713 10AKHOSAA" qs$(10)= "E-DU523 2IGAZELLE" qs$(11)= "M-FU131120 BRILLIANCE" qs$(12)= "E-FS413 24ZSESAVETL" qs$(13)= "G-FU423 3ZSHIVVA" qs$(14)= "C-HU333 85 BROADSWORD" qs$(15)= "G-HS443 30VSE KOEZ" qs$(16)= "F-KS131400 SUSA" qs$(17)= "R-TB432250 LEVIATHAN" So for example, when a Type 17 ship was encountered, I'd find its definition in this table, and extract the fields using left$(), right$(), mid$(), and val(). It's name ("Leviathan") is stored at mid$(qs$(17),12), for example. It's really rough on the heap, I suppose.
  9. Matt's right. Your main program can start with something like 10 poke $9f61,1 :rem point to RAM bank 1 20 load "screendata.bin",8,1,$a000 :rem load screen data 30 poke $9f61,8 :rem point to RAM bank 8 40 load "mapdata.bin",8,1,$a000 :rem load the map Apparently, if the file is larger than 8K, then the loader will simply move to the next bank. So you could load your entire map into banked RAM with one load.
  10. Welcome aboard! Nostalgia is welcome here.
  11. I had this problem with my Traveller Trader game -- the star chart just takes up too much space. The solution is to shove it into a high RAM bank. I'm slowly working on that.
  12. This has been done on the C64; I vaguely recall a Compute! article that a dude pointed out to me in the C64 Software Development forum on Facebook. So, it is possible to do on the X16.
  13. Welcome Hobbyist! I can't wait either
  14. One of the details I'm working out is the trade rules, which are based on a matrix of relationships between two sets of trade codes. This amounts to a hamming distance. I can do this as bits, or code-by-code. If I'm comparing two numbers, then it's a simple AND relationship to get the bits they have in common. But then I have to decode the resulting number to find the count of matching bits. You know, dividing by two and taking the mod, in a loop. On the other hand, if I do a memory comparison, I'm just running through two arrays and incrementing if they're both "on" at each point. It's memory lazy. Is it less code in BASIC to do it this way though? Two arrays of twelve INTs is more than 24 bytes. DIM a1%[11], a2%[11] count=0 for x = 0 to 11 :if a1%[x] = a2%[x] then count = count+1 :next ...that's not bad, assuming I can populate those arrays efficiently.
  15. Thanks for the good advice. I predict two RAM banks are allocated for starmap data, which may need adjustment whenever the player's ship jumps to the next system. That's easily subsumed as shopkeeping during interstellar flight, and a (short) delay is a feature. In fact, a higher quality interstellar drive will reduce that delay. Anyway, that leaves at least 120 RAM banks for anything else. It really isn't Freelancer or Elite, although you've got me thinking. No no no no no SCOPE CREEP!!!! It's more like Star Trader, if you know about that, using Traveller to supplement the rules and data.
  16. The C64 Wiki has a page for the X16. I created a primitive memory map there. https://www.c64-wiki.com/wiki/Commander_X16
  17. rje

    WASD Keyboard

    I got the X16 one with MX Clear switches.
  18. I get that... and yeah, at one point this summer I started writing assembly language that will draw a panel with a specified position and dimension. Just another project to dust off and finish, because I want to use it myself. I've got one in BASIC though, attached here, for your amusement. One version you can load from the emu, and one that's ASCII. WINDOW2.BASpanels.bas
  19. I suffer from premature optimization. I'm continually delayed when thinking about data storage for my Traveller-Trader game. I've done and re-done the same structure many, many, many times, compressing some data while leaving other data alone, thinking about what's easy to use versus what representation reduces wasted memory. First, I'll show you the uncompressed, raw data. Then I'll show you where I've been taking it. The unit of data is the Universal World Profile, which actually includes some star system information, as well. It is data sufficient to run the game, and to add a bit of useful in-game descriptive color. It looks more or less like this: [Regina, A,788899,12, N,S, Ag Ri Cp Sa, G, 138, D, Im, G0 V, M0 D] Now here's one form of the record I devise for these. The map is typically a 50% utilized 8x10 sparse matrix; I like to store the "empty" locations, because just because there's no star doesn't mean nothing's there. In other words, I can hide objects there. $00-0F "Regina" is the name. $10 "A" is the starport code from [A,B,C,D,E,X]. $11-$13 788899 are nybbles representing world characteristics. $14 "12" is the tech level [0-34]. "N,S" are up to two bases from [N,S,D,W, and a few others]. I typically combine them with the starport into a one-byte index. $15-$16 "Ag Ri Cp Sa" are trade comments. I pack these into bitfields across two bytes. "G" is the trade safety rating of [Green, Amber, Red]. I usually pack it with the trade comments. $17 "13" are digit codes for - number of planetoid belts (1), - number of gas giants (3), - and number of other worlds (8) in the system. $18 "D" is the highest ranking noble present. $19 "Im" is a code for the empire this world belongs to. $1A-$1F "G0 V" and "M0 D" are the two stars in the system. These fit nicely into six bytes to store up to three stars. A 32 byte record is very tidy. With a 256 byte header the subsector map fits in 2816 bytes. When I need to read in four of these, I'm only reading 11K. On the other hand, it's a tight space. I was also thinking about a 48 byte record size, which would make the subsector map exactly 4K in size. Reading four of those in would take 16K... not much more than 11K. X16 Considerations Either way, if I read in four subsector maps, I'd be using two RAM banks. Therefore it seems better to go for the larger record size and have a little extra wasted space. Anyone have suggestions? Even if it's "STOP WORRYING ABOUT IT".
  20. I suffer from premature optimization. I'm continually delayed when thinking about data storage for my Traveller-Trader game. I've done and re-done the same structure many, many, many times, compressing some data while leaving other data alone, thinking about what's easy to use versus what representation reduces wasted memory. First, I'll show you the uncompressed, raw data. Then I'll show you where I've been taking it. The unit of data is the Universal World Profile, which actually includes some star system information, as well. It is data sufficient to run the game, and to add a bit of useful in-game descriptive color. It looks more or less like this: [03,10, Regina, A,788899,12, N,S, Ag Ri Cp Sa, G, 138, D, Im, G0 V, M0 D] Now here's one form of the record I devise for these. The map is typically a 50% utilized 8x10 sparse matrix; I like to store the "empty" locations, because just because there's no star doesn't mean nothing's there. In other words, I can hide objects there. $00-0F "Regina" is the name, and I allow 16 bytes for the name. $10 "A" is the starport code, with a range of [A,B,C,D,E,X]. $11-$13 788899 are 4-bit values representing world characteristics. I store them in 3 bytes. $14 "12" is the tech level, with a range from 0 to 34. "N,S" are bases. System may have up to 2 of these from a restricted set of codes. I typically combine them with the starport into a one-byte index. $15-$16 "Ag Ri Cp Sa" are trade comments. I pack these into bitfields across two bytes. "G" is the trade safety rating, from the range [Green, Amber, Red]. I usually pack it with the trade comments. $17 "13" are digit codes for number of planetoid belts (1), number of gas giants (3), and number of other worlds (8) in the system. I typically reduce these into one byte. $18 "D" is the highest ranking nobility present, and store it in one byte. $19 "Im" is a code for the empire this world belongs to ("Imperium" in this case). I store the two characters as is. $1A-$1F "G0 V" and "M0 D" are the two stars in the system. These fit nicely into six bytes to store up to three stars. A 32 byte record is very tidy. With a 256 byte header the subsector map fits in 2816 bytes. When I need to read in four of these, I'm only reading 11K. On the other hand, it's a tight space. I was also thinking about a 48 byte record size, which would make the subsector map exactly 4K in size. Reading four of those in would take 16K... not much more than 11K. X16 Considerations Either way, if I read in four subsector maps, I'd be using two RAM banks. Therefore it seems better to go for the larger record size and have a little extra wasted space. Anyone have suggestions? Even if it's "STOP WORRYING ABOUT IT".
  21. Once you get the feel of it, and get a cheat-sheet, you'll find the PETSCII graphics could be useful for defining the screen panels. More pretty than rows of ========== and ************.
  22. rje

    WASD Keyboard

    An update on the WASD keyboard: I love it, and I didn't expect to. For 17 years I've loved my Topre-switched "Happy Hacker II" keyboard... and I still love its layout. But then I bought the WASD this year, and used it as my primary keyboard, WFH and home use. The Happy Hacker II is my backup, plugged into the same computer, under the auxiliary monitor. It took maybe a month to get used to the feel, and now I prefer it. Now, the Topre keys feel mushy, whereas before I didn't notice. I increasingly prefer the crisp precision of the mechanical switches now. I am officially spoiled. I think that's a good thing -- Kickstarter is okay, but if you don't need it, then don't use it.
  23. Welcome, fellow Texan! I've also been enjoying anew the frustration of BASIC! You'll find this forum a great place for your questions.
×
×
  • Create New...

Important Information

Please review our Terms of Use