Jump to content

All Activity

This stream auto-updates     

  1. Past hour
  2. I promised this thread, so it's time for me to deliver. I said that I would use two 65C02s on the motherboard in an homage to the Fujitsu FM8/7/77 series. That isn't strictly true. I plan to use one 65816 and one (possibly two) Hudson HU6280s. I have several reasons for this: 1: Addressable memory space of 2MB 2: Several powerful mass move instructions (Transfer Alternate Increment, Transfer Increment Alternate, Transfer Increment Increment, Transfer Increment None, and Transfer MPRI Accumulator especially). Why do I chose this particular chip? Because it was on the open market, and used for more than just the NEC PC Engine/TurboGrafx-16. Other applications for the chip include vending machines, jukeboxes, cash registers, electromechanical games (mostly skill cranes, bowling tables and skee-ball machines), and several arcade games by Banpresto and Data East. This (theoretically) makes it an off-the-shelf chip in the Spirit of Woz, at least at the time (Mid Eighties-Early Nineties). With regard to graphics modes: Pixels shall be grouped into vertical sets of seven pixels, arranged in horizontal rows. For the purposes of memory address segmentation, the base increment of pixel set rows is 4. Perhaps not so coincidentally, this results in a character address 4x7 pixels in size, or one pixel in either dimension smaller than the smallest possible readable alphabetical font. Each byte thus maps to 7 single bits of pixel depth, plus the "pallet bit" used by Steve Wozniak to gain extra pixel bit depth. This means that at a projected "Medium" resolution of 288x224, a 7-bit pixel depth would take up 63K, with an actual theoretical color depth 16,384 (128 CLUTs of 128 colors each). In practice, this number is bound to be a little smaller, as most graphics artists will not be so confident in their color needs not include transparency in a majority of their CLUTs. And of course, simply defining those CLUTS will require a specific stretch of at least 20K of Video RAM, and lots and lots of coding. Well, nothing is free. At my planned 7:9 aspect ratio, and taking into account matching spare Video RAM for CLUTs, fonts, and BOBs, a full memory map would result in a 1152x896 display at maximum bit depth per pixel. However, that would translate to a pixel clock higher than the Hu6280 could accommodate on its stock clock. Without a sufficient steady supply of regular new production or new-old stock, I am loath to test any overclock above the stock 7.16 MHz. It looks like it's getting pretty late. I'll continue this at a later date. Questions? Comments? Suggestions? Flames?
  3. Today
  4. I have two 6502 'systems' working in unison in my '8-Bit Wall of Doom' intro but really it's not cooperative or parallel but rather, a semaphore with one KIM-1 (an Uno) waiting on a signal (SIGWAIT) from another 6502 (a Corsham) system; one counts down and the other counts up in Space-Shuttle-Lauch-Sequence style. Not really that exciting since they aren't exactly in Parallel.
  5. The Sega Megadrive, aka Sega Genesis, had a Z80 for audio, in addition to it's main 68000 CPU.
  6. Yesterday
  7. Now I'm afraid to go back and see how much I contributed to this discussion ...
  8. A Commodore friendly STOS is called AMOS. Perhaps those that don't like the choices being made for the X16 should look in to building there own 'dream' computer? Of course everyone else would be unhappy with >>>your<<< choices too, and ask why you can't build it differently? So there would be lots of incompatible computers... just like in the 1980s.
  9. As the OP said, from a technical point of view it's an interesting idea, but practically, it's just a solution looking for a problem to solve. Back in 1979, Atari 8 bits had Antic, Pokey, CTIA/GTIA etc. But they were custom chips and each served a specific purpose. The same with their spiritual successor, the Amiga. Even Atari equipped later machines with a DSP. None had a 2nd general purpose CPU running concurrently. The BBC micro had the brilliant 'Tube' interface, but the co-pro essentially took over the whole system. Anything the 2nd 6502 could do, a dedicated chip will do it better. It would be more interesting to have say a Z80 along with the 6502, then you could run CP/M. Or perhaps something similar to the 'PiTube' for the BBC?
  10. I've read through this topic, and I've come to the same conclusions as I do with many 'programming language' discussions. The people saying the most and shouting the loudest aren't really the target audience. They aren't thinking about others, but about themselves and how they progressed as programmers. They think about what they know and use now, and they want to shape everything to fit in with that. They forget that some people have absolutely no idea of what programming is and need to learn everything from scratch. The absolute basics of programming... learning some simple commands, breaking a problem down in to steps, linking them and getting results. Understanding concepts such as variables, loops, counters and simple logic. Most people don't want to be professional programmers, they may not even want to be "good" programmers. They just want to dabble their toes in the water, experiment, have a bit of fun and see where it takes them. Or maybe just get a pleasant dose of nostalgia. Would you teach somebody to read by starting them off with the works of Prof. Stephen Hawking and perhaps some Tolkien? Do you teach people to count by dropping them straight in to calculus, trigonometry and statistics? Probably not much fun for intermediates, never mind absolute beginners. When you start thinking about being productive and suggesting modern languages, you are clearly missing the point... this is a retro 8 bit platform. Most people already have a PC/Mac for serious stuff. If they wanted to learn 'serious' programming and be 'productive', they are hardly likely to choose this platform are they? Dartmouth BASIC was originally a simple language for students who wanted, or needed, to solve problems, automate calculations or some other process, without having to spend years learning computer science and complicated programming languages. It was ideal for that, and it still is. Nearly all the '80s micros had extended and improved versions of Basic available. Atari, Sinclair, Amstrad and CBM 8 bits had loads. COMAL was essentially an extended, structured version of Basic. They were all easy to learn. Had someone showed me C, Java, Fortran, Javascript or even Pascal as my first experience of programming, I would never even have bothered trying. The Sinclair ZX81 had a wonderful manual to introduce simple programming concepts to 14 year old me, as did my old Atari 400. That led me on to more complicated things, and now I actually like Pascal, and think Psion's OPL was a great little language to mess with. To me, the rest are overcomplicated, hard work and not much fun. There's that word again "FUN". Funny eh?
  11. .org "RODATA" kc_lut: .byte $00, $01, $02, $04, $05, $06, $08, $09, $0A, $0C, $0D, $0E Yeah, that's pretty succinct.
  12. Thanks for your effort at it! After posting the question I felt a little paranoid I just see my codebase growing because of details like this, and at the same time, I'd like to keep the program as small and simple as possible ... But you are right, 12 bytes shouldn't be such a big deal, after all
  13. This obviously could use a helper function to convert the increment, bank number, and channel number to the correct data values to go in the structure. Using this structure is only mildly better than simply brute forcing it, as you did with your first function (although it needs a bank parameter, which I'm sure you already know.) Remember, there are 2 data channels in VERA, and using both of them together is a good way to solve certain problems. So that bit needs to be added to any routine that builds the bit masked control data for writes to or reads from VERA.
  14. rje

    vpoke() for cc65

    Yeah, that's basically how cc65 does it. Just so I can practice thinking about it, here's how cc65 does it. The header file cx16.h has a nice pile of VERA stuff defined. The main bit starts here: #define VERA (*(volatile struct __vera *)0x9F20) So it impresses the struct __vera onto the VERA registers. That structure is really nice, basically laying out the registers so we can simply assign to them directly. It starts like this (and goes on and on): /* A structure with the Video Enhanced Retro Adapter's external registers */ struct __vera { unsigned short address; /* Address for data ports */ unsigned char address_hi; unsigned char data0; /* Data port 0 */ unsigned char data1; /* Data port 1 */ unsigned char control; /* Control register */ ... So for example if I wanted to store a byte on VERA at $1FC10, I'd do this (thank you @Greg King!) VERA.control = 0; // point to Data port 0. VERA.address = 0xfc10; // the address inside VERA. VERA.address_hi = 1; // + the "bank" address inside VERA ($10000) VERA.data0 = the_byte; // my data on Data port 0. NOTE: the .address_hi field is also where you would set the auto increment. So it's not 100% clean... but it's very helpful.
  15. This is the fastest routine I can quickly think of: LDA semitone ; not counting this as this has to happen no matter what alg is used CMP #9 ; 2 cycles BCS @add3 ; 2 | 3 cycles CMP #6 ; 2 BCS @add2 ; 2 | 3 CMP #3 ; 2 BCS @add1 ; 2 | 3 BRA @add0 ; 3 @add3: INC ; 2 @add2: INC ; 2 @add1: INC ; 2 @add0: ORA octave ; 4 ; assume octave is stored pre-shifted into 4 msb STA keycode ; same as LDA semitone So the number of cycles is: 2 + (9|11|13|13) + 4 --> average of 17.5 cycles - so let's call it 18 cycles. a lookup would be something more like: LDX semitone LDA kc_lut,X ; 4+ ORA octave ; 4 STA keycode So twice as fast, requiring 12 bytes of RAM. Given that this operation doesn't happen super-often (pretty much only up to 8 times per frame?) I'd call this "pitayta-pitatta" / "six in one hand, half a dozen in the other" / pick your idiom. In the end, 12 bytes of RAM ain't much to sacrifice, plus the code's a lot easier to read, too.
  16. I don’t know what poke and peek compile to in assembly, but here’s a way to make it be simple under the hood: (*(uint8_t*)0x9F40) = 0x08 = POKE $9F40,8 If you use an explicit address a lot, then you can “name” it with a #define #define YMreg (*(uint8_t*)0x9F40) YMreg = 8; Of course, common system things like VERA, VIA, etc already have these in cx16.h but if there’s a particular address you want to access that’s not already defined in a macro for you, that’s how to do it.
  17. cc65’s documentation is not very helpful to me, at least not the function references. I wish they had example usage for functions, or at least a little discussion of the parameters.
  18. So, the map of the asteroid is based on an icosahedron, the 20 sided Platonic solid: This has been tessellated once; a new vertex created at the midpoint of every edge, with the new vertices extruded out to an equal radius and connected to all their nearest neighbors. This gives a solid with 80 triangular surfaces: There are still only 20 equilateral triangles on this object; the other 60 triangles are isosceles but close to equilateral. Inside each of these triangles we can draw a circle that touches all three sides. Doing so leaves gaps at the vertices upon which we can center some more circles: I did that markup in Paint so it's not perfect but you get the idea. There are 42 vertices and 80 faces, so 122 circles can cover about 78% of the surface. the other 22% is the little gaps between the circles. The orange circles are on equilateral triangles, the red circles are on isosceles triangles, the blue circles are on vertices with 6 edges and the green circles are on vertices with 5 edges. When a circle is in the center of the screen, the image looks exactly the same (with rotations) as it would if you were looking at any other circle of that color. So, as long as each circle has a list of where everything else is relative to itself and some base rotation, the asteroid image centered on any circle can be generated using one of only 4 generic maps. Each triangle is divided into 81 smaller triangles or "cells". There are 18 of those 81 triangles that are outside the circles, which will always remain terrain. For the orange, red, and blue circles that leaves 42 cells, and for the 12 green circles there's 35 cells. This next image shows the 42-cell version in two rotations and the 35 cell version in four rotations: (I used this image to help generate the closeup orthogonal view, by squashing it to a 192:13 aspect ratio, putting gray grid lines on the result, then putting numbers in a spreadsheet according to colors inside grid lines. The spreadsheet took over from there.) The buildings that are going into this game have to fit into 42 cells and still look recognizable without the last 7 cells in the pentagonal map. Here's how I'm indexing these cells for buildings: There are 128 bytes set aside for each building type. The first 42 bytes describe the cells' height from 0 to 7 (bits 4,5, and 6; bit 7 is 0) and a color index from 0 to 15 (bits 0-3). The next 22 bytes aren't allocated yet. The 65th byte is a building type byte. That color nybble in the first 42 bytes does not refer directly to a color on the palette. Instead, it points to a list of 15 day colors and 15 night colors (color index 0 is considered a terrain color, and for that, color is indexed separately by height). So the 15 bytes following the building type byte are the daytime colors, and refer to the palette index. These are followed by a building level byte, and then the 15 night colors. The next 20 bytes aren't allocated yet. The last 12 bytes are used for the building name. For every cell on the map there's a sunset value (0 to 255), and the asteroid has a rotation value (also 0-255), so if sunset minus asteroid rotation is positive the daytime color is shown otherwise the night color is shown. At startup the program goes through each cell on the map and finds the palette index of the day color and night color for each cell and stores those in lookup tables in banked RAM, so the drawing subroutine only needs to switch bank numbers to find sunset, day color, or night color. Why am I showing all of this? I think I'm going to need some help designing buildings. For visualization purposes, each cell is a triangular tower, and each step increase in height is roughly 1/4 of the length of an edge. A max height 7 tower would be almost twice as tall as it is wide. Height 0 is fine; it just means the cell height is the default height of the building area but colored differently than the terrain. The 15 day colors and 15 night colors can be any of the 4096 available colors. Each cell can use only one of those pairs of colors; if it's using #13 for day then it's also using #13 for night. As a fun complication, I'm not going to have just one palette. There will probably be 16 of them, cycling in once every 1/3 of a second. Most of the colors will stay the same from palette to palette, but I'm going to set aside 32 or 64 of them to change from palette to palette. This could lead to some interesting and computationally cheap animation effects. For instance, suppose 4 palette entries are a daytime color, say an amber color most of the time. And another 4 palette entries are a night colors, say a darker brownish color. Suppose that color 1 (both day and night) is gray instead in palettes 0-3, and then amber/brown in palettes 4-F; and that color 2 is amber/brown in palettes 0-3 and 8-F but gray in palettes 4-7; color 3 is gray in palettes 8-B, and color 4 is gray in palettes C-F. Then using those four pairs of cycling colors on cells that are close together could make the illusion of something gray being moved across an amber/brown surface. Or more simply, imagine that a color is gray in most of the palettes but red in palettes 7 and F. Then it would be a blinking red light every couple of seconds. That sort of quick animation would take place simultaneously all over the image, and in the closeup image, all just by loading 512 bytes into VERA every 20 VSYNCH interrupts. It'll make it look like there's a lot more going on than there actually is. So, if anyone wants to take a crack at designing a building, just come up with 42 bytes to describe the height & color index, and a listing of the RGB values for each of the 15 day/night colors, and if any of them are color cycling list the RGB values for that color index for each of 16 palettes. That and 12 Petscii characters for the name. If anyone submits a building I'll probably use it for something in the game. I'm working on a Headquarters building first, as that will always be the first building placed on the map. After that buildings will have to be placed next to existing buildings. The other buildings I have in mind are: - power plant - habitat (probably several examples of this: level 1, level 2 etc) - greenhouse (ditto) - mines of various types - smelter - refinery - foundry - 3D printer (enormous) - storage tanks (various) - warehouses - factory (various types) - maintenance shop - hospital - armory - wretched hive of scum and villainy, with live band - shipyard - launchpad I might write a tool to make it easier to design buildings. If I do, I'll probably share it here.
  19. Hi all, Today I found out by trial and error, that the YM2151 has a weird note encoding. I am talking about the semi tones within an octave. The YM2151 accepts a 4 bit value as semi tone ("NOTE"). Naturally, I would expect the note values to range from 0 to 11 to accommodate for all 12 semi tones. However, the 12 semi tones are spread across the 0...15 range, thus leaving note duplicates in between. (This seems really strange to me, but anyway, I have to deal with it). One possible conversion rule (0...11) --> (0...15) that I found was multiplying X by 4/3 and then rounding down. The conversion rule (0...15) --> (0...11) that I found is: take X and subtract from it the result of integer division X/4 Now, I am interested in a cheap way to get from the 0...11 range to the 0...15 range. I did it with a lookup table, but maybe there is another way that gets away with fewer bytes (12 bytes lookup table + 4 bytes code: TAX LDA semitones_ym2151, X ) Any ideas? If not, I'll accept it as it is ... at least, looking up a value is nicely quick
  20. I finally got around to installing BMCBM (okay, it's called BMC64, but I think it should be rebranded to BMCBM given that it includes five different machines in one package). It booted up to the classic C64 in PAL mode. I switched to NTSC (since I'm in NTSC land) and C128 mode and I finally have a C128 again. I've done very little with it, mind you, but at least I can see it boot and can write little programs on it, as well as switch to C64 mode to play my games that were never ported to C128. Now I just have to dig around more into the settings to figure out what I can and can't do relative to a full blown Vice installation on Windows.
  21. Currently, the increment/decrement must be or'ed into the address expression that's given to vpeek() and vpoke(). No one has taken the time to document a lot of the functions that are available in cc65's libraries. (Usually, someone finds a function in a header, learns that it's very useful to him, notices that it's not in the doc, then submits a patch to "funcref.sgml".) Yep. But, it isn't complete. For example, there are no constants for configuring sprites. "cx16.inc" (for Assembly programming) has much more of that stuff in it.
  22. rje

    vpoke() for cc65

    Turns out that cc65 has vpoke already... and a lot more than that. https://github.com/cc65/cc65/blob/master/include/cx16.h
  23. $9F21 accepts 8 address bits; ANDing the MSB with 0x0f would discard bits 12-15 of the address.
  24. Oh heck, cx16.h has ALL KINDS OF GOOD STUFF. That's what I get for not reading the header file.... Silly me for relying on documentation.
  25. First: beautiful, thank you. I assume there's a way to set the auto-increment? Second: why aren't these functions in the DOCUMENTATION? Am I looking in the wrong place?? https://cc65.github.io/doc/funcref.html
  26. rje

    vpoke() for cc65

    VERA addresses are indeed 17 bits; however, we have to set those 17 bits across three bytes: 0x9f20 gets the LSB, 0x9f21 gets the "middle", and 0x9f22 gets the bank. That points us at our destination address in VERA. THEN we can write the byte.
  27. #include <cx16.h> ... VERA.control = 0; VERA.address = address; VERA.address_hi = 1; VERA.data0 = the_byte; It compiles to the same Assembly code. But, it looks more C-like, less BASIC-like. cc65 also has vpeek() and vpoke() functions. They directly touch VRAM and internal registers.
  1. Load more activity
  • Create New...

Important Information

Please review our Terms of Use