Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VGA: Add fractional pixel scaling #187

Open
MJoergen opened this issue Nov 10, 2020 · 6 comments
Open

VGA: Add fractional pixel scaling #187

MJoergen opened this issue Nov 10, 2020 · 6 comments
Assignees
Labels

Comments

@MJoergen
Copy link
Collaborator

MJoergen commented Nov 10, 2020

This issue is about enabling fractional scaling of the display. The idea is to allow easy implementation of almost-3D games like Wolfenstein or to make smooth 3D text scrolling like in the Star Wars intro! This is for you @sy2002 !!

The idea is to add two new registers that contain the ratio of the pixel width in the screen buffer versus the pixel width on the monitor display, i.e.

VGA$PIXEL_X_SCALE
VGA$PIXEL_Y_SCALE

Each register value contains the size of a screen buffer pixel in units of monitor display pixels, scaled by a constant value of 256. So the default value is 0x0100, corresponding to a scaling factor of 1. The value 0x0080 would mean only half the screen buffer is used to fill the entire monitor display. In other words, this leads to a magnification by a factor of 2.

The implementation could be as easy as expanding the module vga_pixel_counters and adding another set of pixel counter outputs. So one set gives the coordinates on the monitor display (and counts by 1 every clock cycle), and the other set gives the coordinates on the screen buffer (and counts by VGA_PIXEL_X_SCALE/256 every clock cycle). The outputs could be called
monitor_pixel_* and buffer_pixel_*, respectively. Then the monitor_pixel_* signals are fed into the vga_sync module, while the buffer_pixel_* signals are fed into vga_text_mode and vga_sprite etc.

This issue includes writing a cool demo!

@MJoergen MJoergen added the V1.7 label Nov 10, 2020
MJoergen added a commit that referenced this issue Nov 10, 2020
@sy2002
Copy link
Owner

sy2002 commented Nov 10, 2020

@MJoergen Great job! I could not resist to quickly trying your latest commit in branch dev-vga-fractional on real hardware: As you wrote in your email, the whole thing was a bit slow and jerky. But then I removed the line that syncs with the 60 Hz of the screen:

    //while ((y = MMIO(VGA_SCAN_LINE)) >= 480)

And then everything starts to look totally smooth and pretty. I made a small video. Download, unpack and look at this:

IMG_4995.MOV.zip

Now it is a bit too fast.

The solution: I think what we (reads "you?" :-)) might want to add to the monitor (misc library) and then also via qmon.h to C is a simple and synchroneous delay function in microseconds.

Simple and synchroneous means that we do not need the timer interrupt for that. Since we have switched on the cycle-counter be default, it is as easy as counting some cycles (and making sure that we cover wrap arounds). The counters are 48bit or so, so that wrap arounds would only happen every ~65 days if I calculated correctly ;-)

And then we could do a qmon_delay(100000) (which is 0,1 seconds in microseconds) as the function would be defined like qmon_delay(unsigned long microseconds) and then all would be good?

P.S. As your new fractional pixel scaling is not breaking anything, you might want to get rid of the branch and put everything in develop?

@MJoergen
Copy link
Collaborator Author

I'm updated the scrolling to make it more smooth, and I've merged into the develop branch.

Still missing is to update documentation.

It would be nice to make a port of the Wolfenstein game using this new fractional scaling, but I'll leave that to you @sy2002 :-D

@MJoergen
Copy link
Collaborator Author

Regarding the delay, that would be a nice function to have, but I don't see how it can be used in the little demo program. The point is that the demo program is running entirely synchronuous with the VGA scan line. It could be possible to rewrite the demo program using interrupts to control the VGA port, and then have a main loop with delays controlling the parameters for the interrupt. That would probably - in some sense at least - be more cleaner code.

@sy2002 sy2002 removed their assignment Nov 11, 2020
@sy2002
Copy link
Owner

sy2002 commented Nov 11, 2020

@MJoergen I just quickly tried it on hardware: Great job! I love it! ❤️

  • To "unbloat" this issue: I moved making a delay function for the Monitor and for C to a new issue and assigned it to me.

  • A Wolfenstein-ish 3D labyrinth is for sure something that I want to do. So I created another issue and assigned it to me.

  • I guess you can close this issue as soon as you updated the documentation.

@MJoergen
Copy link
Collaborator Author

TODO:

  • Update documentation
  • Make another demo program, showing how to display a checker board in 3D perspective. Perhaps using interrupts?

@sy2002
Copy link
Owner

sy2002 commented Nov 11, 2020

Make another demo program, showing how to display a checker board in 3D perspective. Perhaps using interrupts?

WOW - that sounds great! Can't wait to see that! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants