Pozitron

Discuss anything not related to the current Uzebox design like successors and other open source gaming hardware
olin
Posts: 8
Joined: Sun May 12, 2019 3:16 pm

Pozitron

Post by olin »

Hi,
new poster here, but follow uzebox forum for several years - fantastic project. I thought about building one, but realised I have too many other electronic dev-boards in my drawer, so opted to port it to one of these instead. My hardware of choice was STM32F103VET6, ARM cortex-m3, 64kbytes RAM, 512k flash. I know that ARM CPU is probably not favoured here on the forum for several reasons, so I don't expect anybody to be excited about it. Anyway, the port is still in very early stages, nowhere near where uzebox is today. It does seem to work though, I have the vmode1 working (with demos that use it), audio output working and a crude controller, just enough to be able to test the demos. The aim is to be compatible on source-code level with uzebox demos, with minimal changes in the project makefiles and no resource changes (if possible). So far, that was no issue on the demos I built. I also tried to keep the source code structure the same, so development should tbe familiar for uzebox devs.

Hardware-wise, the idea is to use one of these generic (and cheap) STM dev-boards (maybe even a bluepill ?) and plug them into a custom IO board that is simple to build and solder in hobby conditions. The IO board doesn't exist yet, but should not be that hard to design. If you compare this project (ahh.. did I mention the name is Pozitron?) with BitBox project, Pozitron uses lower grade CPU both in speed and resources, so it fits somewhere in between Uzebox and BitBox. Compared to BitBox, the hardware is based upon existing dev-board (rather than custom made one) to simplify the build process and to keep the cost of the console down.

If you are interested, check out my repo here: https://github.com/ole00/pozitron

Cheers!
olin
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Pozitron

Post by Jubatian »

Could be an interesting project indeed!

64K RAM might actually be enough to get a decent Uzebox port going which doesn't need reflashing, which could be a nice plus (unbounded lifetime).

The ARM versus 8 bit AVR from my perspective boils down to these problems:
  • No DIP solution, although for sure there are plenty of other options. Still, it possibly just misses that feel of handling those nice fat centipedes sitting in old, honest through-hole boards.
  • True emulation is not feasible. I can say this for certain, it is barely feasible for the AVR at 28MHz in a web browser producing proper NTSC graphics, and for the 8 bit Harward architecture AVR there are many spiffy tricks to bump up performance which are simply impossible for the ARM. I tried. It doesn't work. DMA would also be a CPU hog when emulated.
  • Much more investment to get down to the bare metal, the alternative being accepting third-party library bloat (I had seen actual cases, such as "bare metal" USB stack versus ST's solution, this case more than twice the ROM to do the same thing with less control on how it can be done).
So even though I occasionally play around with ARM ideas, I mostly toss them away in the end due to demanding too much work with not too spectacular results, it just feels like a single ARM approach just wouldn't ever be able to deliver the sort of control, versatility and possibility of adaption like the Uzebox hardware does.

To have true emulation at similar performance to the Uzebox, I guess the ARM would have to miss all DMA and run at 6 x NTSC colorburst at most (~21MHz). Could be doable, could be a nice system, but super tricky to get really good video modes out of it. Although at least at this frequency no Flash wait states, so one could go crazy counting cycles :lol:

Sorry, I would rather say just rambling, the idea is still cool even if it was just a spiffy option to run some of the Uzebox codebase on something different! :)
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Pozitron

Post by Jubatian »

Tossing a bit of thought and theoretical video mode assembly design at it, I think it is totally feasible to get a good 6 x NTSC (21MHz) colorburst solution on this HW, capable to recompile Mode 1 / 3 Uzebox games to it. By the assumption that you lay out Video out so it is BBGGGRRR on the low 8 bits, and zeros written to the high bits (pins 8-15 of the port) do no harm. Not that it would be an easy to do thing, just that not impossible.

Sticking to this 21MHz, the maximal resolution would be ~304 pixels, driving a pixel out alternating at 3 / 4 cycles (actually exact square pixels). This is because a jump to register address takes 3 clocks on Cortex-M3 (due to its pipeline design), so any elaborate codeblock (code tile) based generator would be bounded by this limit. However very few Uzebox games use such high resolution modes.

Just random rambling on how it might be viable to get an ARM system with true emulation & reasonable Uzebox compatibility.
olin
Posts: 8
Joined: Sun May 12, 2019 3:16 pm

Re: Pozitron

Post by olin »

Thanks for the input.

Pozitron doesn't try to emulate AVR on ARM. It implements the Uzebox API on ARM natively which means all code runs at the "maximum" possible speed given by the quality of C compiler output. As for the third party library bloat, there is indeed currently some overhead, but that can be optimized out by using the peripheral control registers directly rather than using peripheral api (library). Code size/density doesn't look bad though, comparing the ARM .bin file size to AVR .uze file size the results look like this: DrMario 68100/53910, Megatris 67824/60094, MusicDemo 46988/35900. So it's definitely an increase, but not massive, and so far doesn't seem to be an issue.

Related to 6 x NTSC colorburst speed, Pozitron doesn't try to do any specific frequency matching as the video output doesn't produce colorburst signal. It's RGB only for now, my setup uses SCART. I've used AD724JR IC in the past for generating composite out (and S-video out) and the colorburst was added by the IC itself, so the CPU (ARM or AVR) does not have to worry about it AFAIK. Pozitron of course has to maintain NTSC or PAL video signal timings (length of the porches, V-sync and H-sync timings), but so far I found the timings are not that critical to require 'exact' (or very-specific) CPU frequency. On 96MHz one CPU cycle lasts 10.41 nSec, which is low enough granularity for the video signal, at least for CRT TVs I've tried so far.

DMA videomodes are indeed tricky because DMA shares the memory access with CPU. That means there is a contention between these 2 resources about which one gets priority when accessing the memory. This is solved by setting NVIC priorities (interrupt controller), although not to my absolute satisfaction (teeny tiny shimmering on my LCD panel, not visible on CRT). Another limitation is that DMA requires at least 11 CPU cycles to output 1 pixel (reading 16 bit integer from RAM and writing it to periperal port address, plus some overhead, probably handling the DMA triggers and priority settings). Note, that the DMA runs in parallel with the CPU, so CPU can still do computations related to which tile and which pixel to output etc. DMA request are issued for the whole scanline, therefore while the scanline is rendered by DMA, the CPU can prepare/generate the next scanline's pixel contents in the meantime. This is slightly different compared to Uzebox, as the precise CPU clock cycle counting is not required as long as the scanline generator (the code in specific video-mode routine) can produce the scanline soon enough for the DMA to start the next transfer. In other words, Uzebox needs precise clock counting worth of width of 1 tile, Pozitron does the same but for the width of 1 scanline and CPU does not need to worry about pixelclock as that it maintained by DMA (and the HW timer that drives it). That gives more flexibility how the scanline is produced IMO. Video modes can have different pixel-clocks to change the horizontal resolution to their likings.

BTW. Pozitron's video output is BBGR-BBGGGRRR. That is 12bit video output compatible with Uzebox. Low byte is the same layout as Uzebox with optional high byte that complements the color components to 12 bits - (4 bits per component in total).

Edit: typos and clarity
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Pozitron

Post by Jubatian »

Huh, thanks!

Sorry, I might have been ambiguous when talking about emulation. I didn't want that to come through as you or anyone aimed for true AVR emulation on the ARM. As far as I am aware, that would need at least ~700MHz ARM assuming a Cortex-M3 like architecture & timing.

I was referring to emulation regarding the possibility of emulating Pozitron, or any other homebrew ARM based system on the same principle (video driven directly by code, through DMA or cycle-precise byte-banging). What I was mentioning that one could run the ARM Cortex M3 ALU at ~20MHz (with no DMA) to not exceed the CPU load of the Uzebox emulator. Going higher than that you lose the capability of having an adequate online game player.

This is a somewhat significant problem as sharing games becomes much harder outside the community having the real hardware, or having access to a machine onto which they can download and run a recompiled version (the approach of BitBox). This is not as trivial today than like, say, 5 years ago (centralised app. repositories and such). You absolutely would never be able to get such an ARM system into Libretro, MAME or any such emulation packages as there is no way to emulate it well enough with contemporary computers (much less with some of the more limited systems these emulation packages run successfully on).

Running at a frequency derived from an NTSC colorburst based crystal is indeed not wholly necessary, but actual NTSC is a lot more complex (ingenious engineering) than the colorburst modulated on the luma. There is an excellent blog series on this, here: NTSC demystified. To get the best quality, it is critical to maintain exact ratios between color clocks and the line rate, and also there are a few things to look out for at frame level. This is only really possible if all these run off of the same clock source (even if you do the actual encoding with an encoder chip).

Of course it is up to decision, for example if you design around USB (requiring 48MHz clock), then you would have to accept that if you generated NTSC, it wouldn't be the best (of course NTSC today is mostly for the retro feel, although there are a few cases when you might have that as best option given that there are few displays accepting 15.6KHz line rate).

For me the primary attractiveness of these bigger ARM micros would be that there is a potential to realize a non-lifetime bounded solution by having the games fitting in the RAM, so that's a point where library bloat notably becomes a problem... Of course as long as the game actually needs to carry the entire kernel with itself (I have a couple of designs put aside where it wouldn't).

Just opinions, rather from my perspective than anything absolute.
olin
Posts: 8
Joined: Sun May 12, 2019 3:16 pm

Re: Pozitron

Post by olin »

Update: non-scrolling vmode3 now seems to (kind of) work. Tested on Arkanoid demo. I've compiled LodeRunner demo as well, but it does not work properly (yet). The graphics look OK in LodeRunner, it's just the main character (player) is not displayed and the enemies all run to the single spot on top of the first left ladder (maybe they think the player is there?)...
User avatar
Jubatian
Posts: 1560
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Pozitron

Post by Jubatian »

olin wrote: Mon May 27, 2019 5:50 pmI've compiled LodeRunner demo as well, but it does not work properly (yet).
Could be bugs within the game. Keep in mind that you are compiling for a 32 bit target, while most of these games were written for a 8 bit one, the integer size here is 16 bits (avr-gcc). Integer promotion rules are so different, which can mess up things.

Try compiling Bugz ( https://github.com/artcfox/bugz ) for me it looks like it follows pretty good coding disciplines (and it is non-scrolling). Later when you add scrolling, Joyrider ( https://bitbucket.org/jhhoward/uzeboxracer/src/master/ ), which is designed to be compilable for SDL as well, so could be a very good testbed for your Mode 3 implementation (as the game's codebase is certainly proven functional when compiled with a C compiler targeting 32 bits). If these two games work well, I would say it is pretty likely that your Mode 3 implementation is OK.
olin
Posts: 8
Joined: Sun May 12, 2019 3:16 pm

Re: Pozitron

Post by olin »

Thanks for the tips. Bugz game does work, with small glitches: the timer at the top of the screen starts from 44 instead of 300 (300 - 256). The other small issue is fading which is not implemented in Pozitron's code. How does the fading work in Uzebox? I can see the fading code in the kernel sources that outputs predefined values to DDRC port from the 'fader' array during VSYNC every time the fading is enabled. Are then all pixels multiplied with this DDRC value to produce faded/ blended colors? That seems like a lot of processing... so I guess there must be another trick which is not obvious to me.

Edit: spoke too soon about Bugz. Few more glitches noticed (bugs on intro screen move differently compared to Uzebox emulator) and Pozitron crashed after the first level is completed. Never-mind, will investigate these later.
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Pozitron

Post by Artcfox »

Did you implement pgm_read_word, or just pgm_read_byte?

Code: Select all

#define timeBonus(levelOffset) ((uint16_t)pgm_read_word(&levelData[(levelOffset) + LEVEL_TIME_BONUS_START]))
That expects to read 16 bits, that might explain why the timer wasn't correct in Bugz.
olin
Posts: 8
Joined: Sun May 12, 2019 3:16 pm

Re: Pozitron

Post by olin »

Artcfox wrote: Tue May 28, 2019 2:05 am Did you implement pgm_read_word, or just pgm_read_byte?
That expects to read 16 bits, that might explain why the timer wasn't correct in Bugz.
Bingo! the implementation was there (would not be able to link otherwise), but it was incorrect. It naively expected the parameter is a pointer to u16 rather than u8. After fixing the implementation the Bugz now works without glitches (no timer issue, intro screen bugz move as they should and I can even get to the next level). Excellent observation, thank you!
Post Reply