zaterdag 31 maart 2018

SDL2 Play MP3 or XM

Mix_Music *music = NULL;

For MP3:
 Mix_Init(MIX_INIT_MP3);
 Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 640);
 Mix_Music *music = Mix_LoadMUS("c:\\assembly\\Tennisballen\\x64\\Debug\\test.mp3");
 Mix_PlayMusic(music, 1);

or for XM:
 Mix_Init(MIX_INIT_MOD);
 Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 640);
 Mix_Music *music = Mix_LoadMUS("c:\\assembly\\Tennisballen\\x64\\Debug\\tip - kool.xm");
 Mix_PlayMusic(music, 1);

To End the music:
 Mix_FreeMusic(music);

woensdag 28 maart 2018

SDL2 static link

  • Download the SDL2 sources.
  • Select release configuration.
  • In the VisualC folder, open the visual studio solution.
  • Change the type of project for SDL2 and SDL2main: General -> Configuration Type -> Static Library
  • Configuration Properties -> C/C++ -> Code Generation -> Runtime Library : Multi-threaded (/MT)
  • You should obtain: SDL2.lib and SDL2main.lib
SDL2 dependencies:
Here is the list of dependencies to add in the Linker -> Input of the project you want to compile:
winmm.lib
imm32.lib
version.lib
These libraries are already included in visual studio so it should not be necessary to include them with other lib files.

maandag 19 maart 2018

SDL2 fastest way to draw pixels

When your monitor sync is 60 herz, you've got 16 ms to do your pixel update.
I managed to clear a 1366 by 768 pixelbuffer and upload it to the graphicscard in 0.60ms. This leaves 15 ms to do pixel magic.

In SDL 2, I do the following:

#define DIMx 1366

#define DIMy 768

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmd, int nCmdShow)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,DIMx, DIMy,SDL_WINDOW_SHOWN /*| SDL_WINDOW_FULLSCREEN */);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED /*| SDL_RENDERER_PRESENTVSYNC */);

SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, DIMx, DIMy);
SDL_Surface* surface = SDL_CreateRGBSurface(0, DIMx, DIMy, 32, 0, 0, 0, 0);
BYTE* pixels = (BYTE *)surface->pixels;

SDL_Event event;
bool running = true;

SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);

while (running)
{
int pitch = DIMx * 4;
SDL_LockTexture(texture, NULL, (void **)&pixels, &pitch);
ClearArray(pixels, (DIMx*DIMy/2) );  //0.15 ms (asm: rep stosq)

pixels[0] = 255; //set just one pixel, for example
                pixels[1] = 255;
                pixels[2] = 255;
pixels[3] = 255; 

SDL_UnlockTexture(texture);
SDL_RenderCopyEx(renderer, texture, NULL, NULL, 0.0f, NULL, SDL_FLIP_VERTICAL);
SDL_RenderPresent(renderer);
}

SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}

I hope you can use this code. Activate the SDL_RENDERER_PRESENTVSYNC to have a smooth 60 herz.

Binair bestand downloaden vanuit Javascript

In een eerdere blog heb ik al eens geschreven over createObjectURL, namelijk bij het direct printen vanuit Chrome.
Ook voor het laten downloaden van binaire bestanden is de functie window.URL.createObjectURL handig.

function base64ToArrayBuffer(base64) {
    var binaryString =  window.atob(base64);
    var binaryLen = binaryString.length;
    var bytes = new Uint8Array(binaryLen);
    for (var i = 0; i < binaryLen; i++)        {
        var ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    }
    return bytes;
}

var saveByteArray = (function () {
    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    return function (data, name) {
        var blob = new Blob(data, {type: "octet/stream"}),
            url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = name;
        a.click();
        window.URL.revokeObjectURL(url);
    };
}());

var sampleBytes = base64ToArrayBuffer('R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs');
saveByteArray([sampleBytes], 'black1x1.bin');

Voer deze javascript uit en Chrome download meteen een file genaamd black1x1.bin. Lijkt me zelfs een beetje onwenselijk dat een website zomaar een bestand kan laten downloaden zonder dat je ergens op klikt...

zondag 18 maart 2018

Assembler is sneller dan C++

Gisteren een video gezien van een Assembler expert die uitdrukkelijk beweert dat het een leugen is dat C++ tegenwoordig sneller is dan Assembler.

Laten we een test doen. Bijvoorbeeld een array vullen met 0.

Om maximaal nut te hebben van de 64bits architectuur doe ik het volgende in C++:

Uint64* pixels64bit = (Uint64 *)pixels;
for (int i = 0; i<(DIMx*DIMy/2); i++) { pixels64bit[i] = 0; }

Bovenstaande loop duurt 1.05ms.

Nu in Assembler:
ClearArray proc
    push rdi
    xchg rcx, rdx
    mov rdi, rdx
    xor rax, rax
    rep stosq
    pop rdi
    ret
ClearArray endp

En dat duurt 0.15ms.

Hoe komt het dat de Assembler versie 8 keer sneller is? Als we naar de gegenereerde code van C++ kijken, dan zien we het:

CPP:   Uint64* pixels64bit = (Uint64 *)pixels;
00007FF7F1CE1A9A  mov         rax,qword ptr [pixels]  
00007FF7F1CE1AA1  mov         qword ptr [rbp+218h],rax  
CPP:   for (int i = 0; i<(DIMx*DIMy/2); i++) { pixels64bit[i] = 0; }
00007FF7F1CE1AA8  mov         dword ptr [rbp+234h],0  
00007FF7F1CE1AB2  jmp         wWinMain+1E2h (07FF7F1CE1AC2h)  
00007FF7F1CE1AB4  mov         eax,dword ptr [rbp+234h]  
00007FF7F1CE1ABA  inc         eax  
00007FF7F1CE1ABC  mov         dword ptr [rbp+234h],eax  
00007FF7F1CE1AC2  cmp         dword ptr [rbp+234h],80100h  
00007FF7F1CE1ACC  jge         wWinMain+206h (07FF7F1CE1AE6h)  
00007FF7F1CE1ACE  movsxd      rax,dword ptr [rbp+234h]  
00007FF7F1CE1AD5  mov         rcx,qword ptr [rbp+218h]  
00007FF7F1CE1ADC  mov         qword ptr [rcx+rax*8],0  
00007FF7F1CE1AE4  jmp         wWinMain+1D4h (07FF7F1CE1AB4h)  

Dit kan dus nooit sneller zijn, dan de rep stosq.
Trouwens, een C++ functie zoals:
std::fill(pixels64bit, pixels64bit + (DIMx*DIMy/2), 0);
duurt ook ruim 1.00ms.

zondag 4 maart 2018

fading text

When there is a lot of text to be read, you can fade it to white and give a option to read the rest of the text. This is how it is done in css. You put a gradient absolute positioned block over it.

https://jsfiddle.net/pz1nsrLw/14/

html

<div id="fading">
Dit is een tekst geschreven<br/>
Dit is een tekst geschreven<br/>
Dit is een tekst geschreven<br/>
Dit is een tekst geschreven<br/>
Dit is een tekst geschreven<br/>
Dit is een tekst geschreven<br/>
</div>

css

#fading {
  height: 100px;
  border: 1px solid black;
  position: relative;
  overflow: hidden;
}

#fading:after { 
  content:'';
  width:100%;
  height:5rem;    
  position:absolute;
  left:0;
  bottom:0;
  background-color: black;
  background:linear-gradient(rgba(255,255,255,0), #fff);
}

vrijdag 2 maart 2018

Welke events zijn er met jquery gekoppeld aan een object?

Op de volgende manier kun je kijken welke events jquery gekoppeld heeft op het object window:
$._data( $(window)[0], "events" )