First post, by xorlof
Hi all. I'm new here, but have long been a lurker.
I will start this post my basic question and the provide more detail below in case y'all have other ideas on how I can accomplish my end goal. The basic question:
I'm just getting into understanding the details of creating custom VGA modes. I believe it is pretty simple to set a standard VGA adapter the very compatible 720x480 timings and turn on character mode with 8x3 pixel character cells. This would result in 90x160 very short (3-line-high) character cells on the screen, refreshing at about 60hz. My question is, can the VGA registers be programmed to keep this same (nominal) 720 line by (nominal) 480 timings but increase the overscan area to only output character cells for 80 columns and 144 rows (roughly centered in the screen)?
---
Now the detail if you're curious as to why I'd want this, and if you're all feeling kind enough help guide me even further. I'm starting to work on a Gameboy emulator. I've made one before (for a comparable system, not GB) and now my goal for this new one is to use as many tricks as possible to see just how old/underpowered PC hardware I can get it to run on (minus sound). My current goal is getting a decent number of games working on a fast 286 with bog-standard VGA and standard VGA CRT (at 60Hz to match the Gameboy). One of the tricks I'm exploring is using a character mode to display the graphics. There is a method to this madness, explained next.
The Gameboy screen has 160x144 (square) pixels. Each pixel is one of 4 shades of gray. On the real hardware, what's displayed in that 160x144 area can be thought as a window into a 256x256 pixel area. (Watch this video for about a minute from the linked start point if it's not clear what I'm saying: https://youtu.be/HyzD8pNlpwI?feature=shared&t=1902). Copying pixels around in memory is probably going to be one of the most expensive (time-wise) operations of this emulator because VGA doesn't have suitable graphics acceleration operations. And I need the emulator to cut corners wherever possible (because of the goal stated above). To reduce memory copies, it would be great if we could emulate this 256x256 pixel "canvas" and 160x144 "window" mode. I reckon that if VGA had a 160x144 graphics mode we could do exactly that with correct manipulation of of the start-address and offset registers!
The first thought for implementing this idea was to just use some low resolution graphics mode as the basis for such a thing and increase the overscan area (if possible) to cut available pixels down to the needed 160x144. However, if using 320x200 timings as a basis for this, the overscan area would be huge and the emulated screen would be really small, occupying only about 1/3th of the usual non-overscan area . The best compromise I could come up with was this 80x144 character mode (with each "character being two pixels horizontally, one using the background color and one the foreground color). That image would occupy about 80% of the usual non-overscan area (and expanded a bit horizontally. Reducing this width expansion was the reason for wanting to start with 720x480 timings, rather than 640x480 timings). Character mode has the annoying disadvantage that every other byte has to be the character code. I don't know if I can work around that by messing with the various write modes and planes and such (I haven't taken the time to digest how that works yet).
Anyway, if you've got as better idea of how to do what I'm trying to accomplish, I'm all ears! One other thing I was thinking of investigating is seeing if some hacked 256-color mode could take advantage of the fact that a 256x256 pixel canvas would take up exactly 64KB and maybe would allow wrapping back up to the top of a 64kb memory segment, sort of like in the Donkey Kong Country example shown in the video linked above. The gurus out there probably know some tricks to get closer to creating a regular graphics mode that mostly fills the screen and runs at 60hz. For example, according to this: http://www.osdever.net/FreeVGA/vga/crtcreg.htm#09, in graphics modes the Maximum Scan Line register can be used to repeat scanlines, so with the 720x480 timings, perhaps this could be used to triple each scanline (kinda like how my "short character mode" let's us fill 3 pixels height at once), getting me a step closer to a that 160x144 graphics mode. I need to experiment.
Thanks in advance for your help and advice!