|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Author | Message |
---|---|
|
Pushing the VDP to do things during the hblank, but using C?
Posted: Tue Dec 12, 2023 12:25 am
|
I'm just playing around with ideas, and found from reading it's possible to have the SMS display 64 colours at once, with the caveat of colours changing during an h-blank (which is itself a very vague and time sensitive period). I'm using devkitSMS' SMS_setLineInterruptHandler() but I suspect that because C the compiled code is probably not fast/sensitive enough to do things with the palette during the variable hblank.
This seems to be related to https://www.smspower.org/forums/19058-WhenDoesAnHBlankStart where the dots are part of what the CRAM is doing. From reading, h scrolling seems very consistent because it's latched, but palette changes are highly variable. Like this is fine for hscrolling offset stuff: SMS_setLineInterruptHandler(&scrollInterruptHandler); SMS_setLineCounter(24); // Every 25 scanlines SMS_enableLineInterrupt(); I'm thinking if I wanted to pursue things like mid-screen palette changes I'd have to write this part in assembly for speed. I'm a little less confident in the code from that linked thread, in the sense of how I'd integrate it back into C given I'm not writing everything in asm. I've got some other parts in assembly so it's not a problem of assembly per se, more of how to do fancier things like hooking interrupts in asm, within the context of C doing things like calling wait for Vblank, updating the PSG audio frame etc. At the very least I could always mix background tiles varying which tile + sprite palettes to get 32 colours, although it'd probably be a case of designing the art very carefully so that it wasn't trying to use a different palette every other tile... hmm. Anyway, I'm not super worried if it's hard or nigh-impossible to do, this is more of an intellectual exercise. Would anyone have any tips or examples for handling very frequent hblanks or ways to handle palette changes during an hblank avoiding CRAM garbage with a mix of C and asm? Or am I chasing an impossible dream? |
|
|
Posted: Tue Dec 12, 2023 7:07 am |
You can have a look at what I did to encapsulate Maxim's sample library in a C wrapper here:
https://github.com/kusfo/sms-fxsample/blob/master/fxsample.c You can do the same for the hblank handler |
|
|
Posted: Tue Dec 12, 2023 10:02 am |
The hblank fires “early” such that by the time your code runs, it’s in the active display; games therefore waste cycles to push the CRAM dots into the border/hblank proper. However, this means that you can only really change a few colours per scanline. I’m not sure how easy it is to do small cycle-counted delays in C, I guess you can inline asm some nops or maybe the optimiser is bad enough that you can use junk code to slow it down.
Another approach (taken by Sonic the Hedgehog) is to draw noisy flashing sprites in the area where the CRAM dots will be and hope nobody notices. That way you can change more. |
|
|
Posted: Tue Dec 12, 2023 10:21 am |
It depends. Writing to CRAM will always cause those dots to appear on screen, the best you can do is to try to push them as close as possible to a screen edge and hope the TV cuts them out. But if you want to update more than one palette entry, you probably need to make sure that only one entry gets updated each line, which is not easy to do but it's possible, given that it's possible to -more or less- precisely time an hblank interrupt. Then it's all about updating one entry and waste exactly enough cycles to get to the next update at the correct time, in a loop. This isn't something impossible to do with C, but it needs some trial and error. A few cycles delay could be added wherever you need using a bit of inline asm code such as __asm
nop ; each NOP takes 4 cycles, place how many NOPs as you need here __endasm; |
|
|
Posted: Tue Dec 12, 2023 10:25 am |
It's not so much a question of compiled C not being generally fast enough, since we're compiling down to bare metal, not through any kind of OS layer, and most of the time critical functions in devkitsms are written in assembler anyway; so really it's just a question of what devkitsms's builtin interrupt handler happens to be doing. And that's pretty easy to see by looking at the code, here: https://github.com/sverx/devkitSMS/blob/b34cfb83907509d7351cd1f37d17941998041083/SMSlib/src/SMSlib.c#L375 So if you count the instructions you can figure out when your horizontal scanline handler will actually be called, to a high degree of confidence. If it's not quick enough you might have to override the root ISR somehow. Note that `SMS_isr` is called directly from a `jp` at $0038, here. |
|
|
Posted: Tue Dec 12, 2023 12:25 pm |
Aha, interesting. Thanks for the replies, it's given me some stuff to look into. Appreciate it! I'll see how things go. | |
|
Posted: Thu Dec 14, 2023 7:02 am |
Currently, I have a platforming engine running with line handler based effects (like 4 rows header, parallax scrolling o palette changes to simulate underwater color changes) working without issues.
... but it is not easy, you have to calibrate all the functions to avoid clashes between the frame/line handlers and the vram updates (tile/tilemap updates, by example). The color changes (inside screen) generate that weird cram color pixel effects, yeah. |
|