pouët.net

The official TMDC20 thread

category: general [glöplog]
Here's a feasibility study table for anyone who's thinking of making a table based rgb->text mode converter..

BB Image
added on the 2017-11-11 19:16:56 by sol_hsa sol_hsa
For those interested, the demos I've been making are using a 3x3x3 grid.Thats the smallest one I found that handles pipes and slashes and dashes.
3 levels of brightness doesn't seem a lot, but it really is 3 levels of local contrast, if you allow coloring.
added on the 2017-11-12 05:53:44 by BarZoule BarZoule
wow, my account --it still exists; I could have sworn I found it removed at one point

Some days ago I accidentally discovered that GetTickCount() consistently has a resolution of 16ms, give or take a ms, at least on Windows 10. At first, I figured that this was a hidden vsync thing, but setting my refresh rate to 75hz didn't drop it down to 13ms. Does that mean it's simply the Windows kernel quantum length?

I made a little experiment (forgive my possibly ugly C code)

At 60hz, there's no visible tearing that I can see, yet it 'skips'; it's not smooth like I hoped.
I'm sure once I try it on my 75hz laptop it'll be even more stuttery.

Everywhere I search for vsync or tying a callback to vertical retrace, I find statements along the lines of "it's only possible in fullscreen." Clearly, that's not the case. You can do vsync in javascript now, within a not-fullscreen browser window.

So how do I find when vblank happens within Windows 5.0+, without violating the "no graphics acceleration" (which I assume means absolutely no GL/DX) rule? Not exactly specific to textmode, but still...
added on the 2017-11-16 08:16:31 by QUINTIX QUINTIX
Hmm, seems i never actually cared about any timing...
...this is the complete code for TextMode TVnoise by Tristar & Red Sector Inc.:

Code: int form, color; int charset[5] = { 0xdb, 0xdc, 0xb1, 0xfe, 0xdf }; int palette[2] = { 0, 15 }; HANDLE wHnd; // Handle to write to the console. HANDLE rHnd; // Handle to read from the console. //°°°°°°°°°°°°°°°°° //°°°°° MAIN int main(int argc, char* argv[]) { // Set up the handles for reading/writing: wHnd = GetStdHandle(STD_OUTPUT_HANDLE); rHnd = GetStdHandle(STD_INPUT_HANDLE); // Change the window title: SetConsoleTitle("hArDy - TextMode TV Noise"); // Set up the required window size: SMALL_RECT windowSize = {0, 0, 79, 49}; // Change the console window size: SetConsoleWindowInfo(wHnd, TRUE, &windowSize); // Create a COORD to hold the buffer size: COORD bufferSize = {80, 50}; // Change the internal buffer size: SetConsoleScreenBufferSize(wHnd, bufferSize); // Set up the character buffer: CHAR_INFO consoleBuffer[80*50]; // Set up the positions: COORD charBufSize = {80,50}; COORD characterPos = {0,0}; SMALL_RECT writeArea = {0,0,79,49}; do { for (int y=0; y<50; ++y) { for (int x=0; x<80; ++x) { // float random = rand(); float random = 1.0f; color = (int)random % 2; form = (int)(random*999) % 5; consoleBuffer[x+80*y].Char.AsciiChar = charset[form]; consoleBuffer[x+80*y].Attributes = palette[color]; } } // Write the characters: WriteConsoleOutput(wHnd, consoleBuffer, charBufSize, characterPos, &writeArea); } while (!GetAsyncKeyState(VK_ESCAPE) ); // Exit return 0; }
Quote:
Everywhere I search for vsync or tying a callback to vertical retrace, I find statements along the lines of "it's only possible in fullscreen." Clearly, that's not the case. You can do vsync in javascript now, within a not-fullscreen browser window.

Yeah, except that microsoft apparently hates textmode demos; vsync hasn't been possible in text mode since win95 or so. =)
added on the 2017-11-16 09:47:02 by sol_hsa sol_hsa
Quote:
Yeah, except that microsoft apparently hates textmode demos; vsync hasn't been possible in text mode since win95 or so. =)

I don't need perfect vsync. In fact, upon more research, it looks like DWM in Windows 6.0+ (vista,7,8, 9 -0.9,10) pretty much takes care of that by triple buffering all the things.

To clarify:
I wish to 1) minimize, not necessarily eliminate, tears in Win XP/2000
2) minimize, not necessarily eliminate, dropped frames
And given it's possible to synchronize timing with the monitor across platforms in a freaking browser window I don't think that's an unreasonable request, even for windowed textmode :p

Further experimentation: I finally managed to try my initial code on my laptop. At 75hz, it drops no frames that I can tell, but I get anything but a smooth 5:4 pulldown for my 16ms interval. It's all sorts of janky.

Looks like the only way to get less than 16ms is to use "multimedia timers,"
So I gave a contrived hardcoded-to-13ms alteration a shot
Code: //narrow bar void nbar(CHAR_INFO buff[4000], int pos, int col) { if (pos < 0 || pos > 159) { return; } col &=0xF; if( pos & 1){ col <<= 4;} const CHAR_INFO bar = {0xDD,col}; const CHAR_INFO black = { ' ', 0 }; for (int i = 0; i < 80; i++) { buff[i] = black; } buff[pos >> 1] = bar; CHAR_INFO* firstLine = buff; for (CHAR_INFO* curLine = &buff[80]; curLine < &buff[80 * 49 + 1]; curLine += 80) { memcpy_s((void*)curLine, sizeof(CHAR_INFO) * 80, (void*)firstLine, sizeof(CHAR_INFO) * 80); } } VOID CALLBACK myCallBack( _In_ PVOID lpParameter, _In_ BOOLEAN TimerOrWaitFired ){ static SHORT pos = 0, yPos =0; CONST HANDLE hdl = *(HANDLE*) lpParameter; CHAR_INFO buff[80 * 50]; nbar(buff,pos,15); pos = (pos + 1) % 160; SMALL_RECT recv = { 0, 0, 79, 49 }; if(TryEnterCriticalSection(&ScreenBuffCriticalSection)) { WriteConsol eOutput(hdl, buff, { 80, 50 }, { 0, 0 }, &recv); LeaveCriticalSection(&ScreenBuffCriticalSection); } };

and
Code: ... InitializeCriticalSectionAndSpinCount(&ScreenBuffCriticalSection,0x20 0); ...//critical section may be entirely unneeded, but I'm paranoid TIMECAPS tc; UINT wTimerRes; if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { return -1;} #define TARGET_RESOLUTION 13 // 13 ms test wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax); timeBeginPeriod(wTimerRes); ... done = !CreateTimerQueueTimer(&timer,NULL,&myCallBack,(PVOID)&hdl,100, wTimerRes, WT_EXECUTEDEFAULT); //esc key busywait goes here

It's definitely a lot smoother at 75hz; though it actually visibly tears every few seconds or so (I can tolerate that, though behavior under XP remains doubtful), but there are frequent dropped frames, likely due to the fact that (13ms)^-1 ~ 77hz.

In the unlikely case I produce just above BITS level compofiller before the deadline, I'd rather not hardcode it to a particular refresh rate. I want a (close enough to) vretrace callback.

Ed: is it just me or is Pouet's bbcode error checker complaining about buff[i] = black?
added on the 2017-11-16 16:43:50 by QUINTIX QUINTIX
Code: DWM_TIMING_INFO timing_info; timing_info.cbSize = sizeof(timing_info); const HRESULT result = DwmGetCompositionTimingInfo(NULL,&timing_info); ... cout << timing_info.qpcRefreshPeriod << " : qpcRefreshPeriod\n"; cout << timing_info.qpcVBlank << " : qpcVBlank\n"; LARGE_INTEGER freq; const bool qpf_fail = QueryPerformanceFrequency(&freq); //grab QPC ticks per sec ULONGLONG ullFreq = freq.QuadPart; QPC_TIME qpcRefresh = timing_info.qpcRefreshPeriod; double refreshFreq = ullFreq / timing_info.qpcRefreshPeriod; cout << refreshFreq << " : hz"; //timing_info already has the integer ratio, this is a sanity check to see if qpcRefreshPeriod means what I think it means const HANDLE hdl = GetStdHandle(STD_OUTPUT_HANDLE); ULONGLONG max=0; long long diff; while (!GetAsyncKeyState(VK_ESCAPE)) { SetConsoleCursorPosition(hdl,{0,8}); //write over prior const HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info); LARGE_INTEGER curtime; QueryPerformanceCounter(&curtime); diff = timing_info.qpcVBlank - curtime.QuadPart; //time to next vblank in qpc ticks if (abs(diff) > max){max = diff;} //for comparison to qpcRefreshPeriod, should approach but never touch printf_s("%10lld until next vblank\n", diff); printf_s("%10lld longest wait", max); }

This looks extremely promising, as it behaves as expected. max(diff) does in fact approach qpcRefreshPeriod. Trouble is DWM is Vista+ only. Would an executable still run in XP if, upon checking the windows version to be XP, the codepath calling DwmGetCompositionTimingInfo is never touched? Or would the VS compiler set the minimum version of windows required for the outputed exe just by the existence of that function call?

I'm likely making this a far bigger deal than it actually is, maybe I shouldn't fuss with this anymore until I have some effects and animations carefully planned, mostly coded & benchmarked.
added on the 2017-11-16 21:07:30 by QUINTIX QUINTIX
Quote:
I'm likely making this a far bigger deal than it actually is, maybe I shouldn't fuss with this anymore until I have some effects and animations carefully planned, mostly coded & benchmarked.

Quite probably yes, but on the other hand, sometimes it's the little things that really make a difference.
added on the 2017-11-17 10:57:40 by sol_hsa sol_hsa
Quintix: I am glad you are asking these questions. I have never been clear on textmode vsync. I asked about it a while ago, and somebody told me not to worry about it, but I've never been 100% happy with that answer.

You can always load Dwm functions dynamically. Something like this (not tested) ---

Code:HRESULT WINAPI (*myDwmGetCompositionTimingInfo)(HWND hwnd, DWM_TIMING_INFO *pTimingInfo) = NULL; HINSTANCE dwm_dll = LoadLibrary("dwmapi.dll"); if(dwm_dll != NULL) myDwmGetCompositionTimingInfo = GetProcAddress(dwm_dll,"DwmGetCompositionTimingInfo");


Then you can call it as myDwmGetCompositionTimingInfo(hwnd, whatever). If you do not link with dwmapi.lib, you should be able to run fine even on platforms where dwm doesn't exist.
added on the 2017-11-17 15:34:00 by cxw cxw
sol: in the past 'realtime converters' where not really welcome in the tmdc compo (atleast from what i got out of the jury comments). has that changed?

anyways here's some dithering converter for the sake of
BB Image
added on the 2017-11-18 14:21:20 by the_Ye-Ti the_Ye-Ti
Quote:
sol: in the past 'realtime converters' where not really welcome in the tmdc compo (atleast from what i got out of the jury comments). has that changed?


I don't know what you're talking about =) basically all textmode demos do some kind of bitmap to ascii conversion. What was frowned upon is the fact that everybody kept using the exact same converters which got a bit boring.

Anyway, I haven't run TMDC since tmdc10..
added on the 2017-11-18 15:13:09 by sol_hsa sol_hsa
ah i see :) must be my negative attitude
added on the 2017-11-18 16:30:37 by the_Ye-Ti the_Ye-Ti
Quote:
You can always load Dwm functions dynamically. Something like this (not tested)

Note that you can also tell the linker to delay-load specific libraries. This way, the executable will still run if the specific dependency is not found, but it will crash when trying to call a function from that DLL. The nice thing is that you can keep your code unmodified, but use LoadLibrary + GetProcAddress to check if the DLL is present and contains the function you want to call. If you verified that, you can keep using the function as if you had linked it the "normal" way.
Thanks cxw & Saga

Back to more pertinent topics of massive lookup tables
BB Image
I've spent the better part of the week trying to make the beginnings of one, the kinds of which I've yet to see used in a textmode demo. I doubt rapidly flipping between two characters every frame would count as "glitch mode" (or at least I hope it isn't).

But I'm still figuring where to go from here. Vague idea I'm clinging to is that jpeg happens to use 8x8 fixed marcoblocks. DCT coefficients may be plenty good enough for use as some sort of searchable hashmap. Isn't that how the original photomosaic tool of the late 90's worked?
added on the 2017-11-19 05:09:27 by QUINTIX QUINTIX
Quote:
I doubt rapidly flipping between two characters every frame would count as "glitch mode" (or at least I hope it isn't).

Well, it's not, but it looks painful. Also, a few TMDC's back someone did this and the youtube capture looks *awesome*, because it kills the flickering, but watching it "live" wasn't as much fun.

Quote:
But I'm still figuring where to go from here. Vague idea I'm clinging to is that jpeg happens to use 8x8 fixed marcoblocks. DCT coefficients may be plenty good enough for use as some sort of searchable hashmap. Isn't that how the original photomosaic tool of the late 90's worked?

Would love to see the results if you try this =)
added on the 2017-11-20 14:52:51 by sol_hsa sol_hsa
Quote:
Well, it's not, but it looks painful. Also, a few TMDC's back someone did this and the youtube capture looks *awesome*, because it kills the flickering, but watching it "live" wasn't as much fun.


Also, it will be affected a lot by the output technology. CRT and projectors will probably induce headaches bit look right, while LCDs will smooth the thing out but maybe not at the same rate for each channel or following a straight curve, introducing weird colors, like peeks of green when mixing black and white. Worse thing is, it will be different from monitor to monitor.
That ring said, it could still be interesting, especially if you know the display setup won't change.
added on the 2017-11-22 17:54:59 by BarZoule BarZoule

login