/*
Retro TV effect for NSpire
Copyright (C) 2012 Daniel Tang
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#define SCREEN_BYTES_PERPIXEL (SCREEN_BYTES_SIZE/(SCREEN_WIDTH*SCREEN_HEIGHT))
#define HOOK_ADDR 0x100b97b4 /* OS 3.1 TI-NSpire CX. nts: needs better hooking place */
HOOK_DEFINE(screen_blip) {
int halfheight = SCREEN_HEIGHT/2, halfwidth = SCREEN_WIDTH/2;
char * scrbase = SCREEN_BASE_ADDRESS;
void * scr = malloc(SCREEN_BYTES_SIZE);
if (scr) {
memcpy(scr, SCREEN_BASE_ADDRESS, SCREEN_BYTES_SIZE);
}
memset(scrbase, 0xff, SCREEN_BYTES_SIZE);
while (halfheight > 1) {
size_t blackamount, whiteamount;
char * scrptr = scrbase;
blackamount = SCREEN_WIDTH*SCREEN_BYTES_PERPIXEL;
blackamount *= (SCREEN_HEIGHT/2) - halfheight;
whiteamount = SCREEN_WIDTH*SCREEN_BYTES_PERPIXEL;
whiteamount *= halfheight;
memset(scrptr, 0x00, blackamount);
scrptr += blackamount;
//memset(scrptr, 0xff, whiteamount*2);
scrptr += whiteamount*2;
memset(scrptr, 0x00, blackamount);
halfheight -= 4;
sleep(1);
}
memset(scrbase, 0x00, SCREEN_BYTES_SIZE);
scrbase = SCREEN_BASE_ADDRESS + (SCREEN_WIDTH*SCREEN_BYTES_PERPIXEL*((SCREEN_HEIGHT/2)-1));
sleep(10);
while (halfwidth > 1) {
size_t blackamount, whiteamount;
char * scrptr = scrbase;
whiteamount = halfwidth*2*SCREEN_BYTES_PERPIXEL;
blackamount = (SCREEN_WIDTH*SCREEN_BYTES_PERPIXEL) - whiteamount;
blackamount /= 2;
memset(scrptr, 0x00, blackamount);
scrptr += blackamount;
memset(scrptr, 0xff, whiteamount);
scrptr += whiteamount;
memset(scrptr, 0x00, blackamount);
scrptr += blackamount;
memset(scrptr, 0x00, blackamount);
scrptr += blackamount;
memset(scrptr, 0xff, whiteamount);
scrptr += whiteamount;
memset(scrptr, 0x00, blackamount);
scrptr += blackamount;
halfwidth -= 4;
sleep(1);
}
if (scr) {
memcpy(SCREEN_BASE_ADDRESS, scr, SCREEN_BYTES_SIZE);
free(scr);
}
HOOK_RESTORE_RETURN(screen_blip);
}
int is_already_hooked(unsigned* ptr) {
return (memcmp(ptr,"\x00\x70\x86\xe5",4) != 0);
}
int main(int argc, char* argv[]) {
if (argc == 2 && strncmp("hook",argv[1],4) == 0) {
HOOK_INSTALL(HOOK_ADDR, screen_blip);
return 0;
}
if (is_already_hooked((unsigned*)HOOK_ADDR)) {
show_msgbox("Screen blip","Hook was already installed.");
return 0;
}
struct stat stats;
stat(argv[0], &stats);
void* ptr = malloc(stats.st_size);
if (!ptr) {
char buffer[256];
sprintf(buffer, "Failed to malloc %d bytes!", stats.st_size);
show_msgbox("Error",buffer);
return -1;
}
FILE* fp = fopen(argv[0], "rb");
if (!fp) {
free(ptr);
show_msgbox("Error","Failed to fopen!");
return -1;
}
fread(ptr, 1, stats.st_size, fp);
fclose(fp);
clear_cache();
((void (*)(int,char*[])) ptr)(2, (char*[]){ argv[0], "hook", NULL });
show_msgbox("Screen blip","Hook installed successfully");
return 0;
}