Initial commit - http://sourceforge.net/p/fceumm/code/160/
This commit is contained in:
86
src/drivers/common/args.c
Normal file
86
src/drivers/common/args.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains code for parsing command-line */
|
||||
/* options. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../fceu-types.h"
|
||||
#include "args.h"
|
||||
|
||||
void ParseEA(int x, int argc, char *argv[], ARGPSTRUCT *argsps) {
|
||||
int y = 0;
|
||||
|
||||
do {
|
||||
if (!argsps[y].name) {
|
||||
ParseEA(x, argc, argv, (ARGPSTRUCT*)argsps[y].var);
|
||||
y++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[x], argsps[y].name)) { // A match.
|
||||
if (argsps[y].subs) {
|
||||
if ((x + 1) >= argc)
|
||||
break;
|
||||
if (argsps[y].substype & 0x2000) {
|
||||
((void (*)(char *))argsps[y].subs)(argv[x + 1]);
|
||||
} else if (argsps[y].substype & 0x8000) {
|
||||
*(int*)argsps[y].subs &= ~(argsps[y].substype & (~0x8000));
|
||||
*(int*)argsps[y].subs |= atoi(argv[x + 1]) ? (argsps[y].substype & (~0x8000)) : 0;
|
||||
} else
|
||||
switch (argsps[y].substype & (~0x4000)) {
|
||||
case 0: // Integer
|
||||
*(int*)argsps[y].subs = atoi(argv[x + 1]);
|
||||
break;
|
||||
case 2: // Double float
|
||||
*(double*)argsps[y].subs = atof(argv[x + 1]);
|
||||
break;
|
||||
case 1: // String
|
||||
if (argsps[y].substype & 0x4000) {
|
||||
if (*(char**)argsps[y].subs)
|
||||
free(*(char**)argsps[y].subs);
|
||||
if (!(*(char**)argsps[y].subs = (char*)malloc(strlen(argv[x + 1]) + 1)))
|
||||
break;
|
||||
}
|
||||
strcpy(*(char**)argsps[y].subs, argv[x + 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (argsps[y].var)
|
||||
*argsps[y].var = 1;
|
||||
}
|
||||
y++;
|
||||
} while (argsps[y].var || argsps[y].subs);
|
||||
}
|
||||
|
||||
void ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps) {
|
||||
int x;
|
||||
|
||||
for (x = 0; x < argc; x++)
|
||||
ParseEA(x, argc, argv, argsps);
|
||||
}
|
||||
|
||||
12
src/drivers/common/args.h
Normal file
12
src/drivers/common/args.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef _DRIVERS_ARGH
|
||||
typedef struct {
|
||||
char *name;
|
||||
int *var;
|
||||
|
||||
void *subs;
|
||||
int substype;
|
||||
} ARGPSTRUCT;
|
||||
|
||||
void ParseArguments(int argc, char *argv[], ARGPSTRUCT * argsps);
|
||||
#define _DRIVERS_ARGH
|
||||
#endif
|
||||
467
src/drivers/common/cheat.c
Normal file
467
src/drivers/common/cheat.c
Normal file
@@ -0,0 +1,467 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "../../driver.h"
|
||||
|
||||
static void GetString(char *s, int max) {
|
||||
int x;
|
||||
fgets(s, max, stdin);
|
||||
|
||||
for (x = 0; x < max; x++)
|
||||
if (s[x] == '\n') {
|
||||
s[x] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get unsigned 16-bit integer from stdin in hex. */
|
||||
static uint32 GetH16(unsigned int def) {
|
||||
char buf[32];
|
||||
|
||||
fgets(buf, 32, stdin);
|
||||
if (buf[0] == '\n')
|
||||
return(def);
|
||||
if (buf[0] == '$')
|
||||
sscanf(buf + 1, "%04x", &def);
|
||||
else
|
||||
sscanf(buf, "%04x", &def);
|
||||
return def;
|
||||
}
|
||||
|
||||
/* Get unsigned 8-bit integer from stdin in decimal. */
|
||||
static uint8 Get8(unsigned int def) {
|
||||
char buf[32];
|
||||
|
||||
fgets(buf, 32, stdin);
|
||||
if (buf[0] == '\n')
|
||||
return(def);
|
||||
sscanf(buf, "%u", &def);
|
||||
return def;
|
||||
}
|
||||
|
||||
static int GetI(int def) {
|
||||
char buf[32];
|
||||
|
||||
fgets(buf, 32, stdin);
|
||||
if (buf[0] == '\n')
|
||||
return(def);
|
||||
sscanf(buf, "%d", &def);
|
||||
return def;
|
||||
}
|
||||
|
||||
static int GetYN(int def) {
|
||||
char buf[32];
|
||||
printf("(Y/N)[%s]: ", def ? "Y" : "N");
|
||||
fgets(buf, 32, stdin);
|
||||
if (buf[0] == 'y' || buf[0] == 'Y')
|
||||
return(1);
|
||||
if (buf[0] == 'n' || buf[0] == 'N')
|
||||
return(0);
|
||||
return(def);
|
||||
}
|
||||
|
||||
/*
|
||||
** Begin list code.
|
||||
**
|
||||
*/
|
||||
static int listcount;
|
||||
static int listids[16];
|
||||
static int listsel;
|
||||
static int mordoe;
|
||||
|
||||
void BeginListShow(void) {
|
||||
listcount = 0;
|
||||
listsel = -1;
|
||||
mordoe = 0;
|
||||
}
|
||||
|
||||
/* Hmm =0 for in list choices, hmm=1 for end of list choices. */
|
||||
/* Return equals 0 to continue, -1 to stop, otherwise a number. */
|
||||
int ListChoice(int hmm) {
|
||||
char buf[32];
|
||||
|
||||
if (!hmm) {
|
||||
int num = 0;
|
||||
|
||||
tryagain:
|
||||
printf(" <'Enter' to continue, (S)top, or enter a number.> ");
|
||||
fgets(buf, 32, stdin);
|
||||
if (buf[0] == 's' || buf[0] == 'S') return(-1);
|
||||
if (buf[0] == '\n') return(0);
|
||||
if (!sscanf(buf, "%d", &num))
|
||||
return(0);
|
||||
if (num < 1) goto tryagain;
|
||||
return(num);
|
||||
} else {
|
||||
int num = 0;
|
||||
|
||||
tryagain2:
|
||||
printf(" <'Enter' to make no selection or enter a number.> ");
|
||||
fgets(buf, 32, stdin);
|
||||
if (buf[0] == '\n') return(0);
|
||||
if (!sscanf(buf, "%d", &num))
|
||||
return(0);
|
||||
if (num < 1) goto tryagain2;
|
||||
return(num);
|
||||
}
|
||||
}
|
||||
|
||||
int EndListShow(void) {
|
||||
if (mordoe) {
|
||||
int r = ListChoice(1);
|
||||
if (r > 0 && r <= listcount)
|
||||
listsel = listids[r - 1];
|
||||
}
|
||||
return(listsel);
|
||||
}
|
||||
|
||||
/* Returns 0 to stop listing, 1 to continue. */
|
||||
int AddToList(char *text, uint32 id) {
|
||||
if (listcount == 16) {
|
||||
int t = ListChoice(0);
|
||||
mordoe = 0;
|
||||
if (t == -1) return(0); // Stop listing.
|
||||
else if (t > 0 && t < 17) {
|
||||
listsel = listids[t - 1];
|
||||
return(0);
|
||||
}
|
||||
listcount = 0;
|
||||
}
|
||||
mordoe = 1;
|
||||
listids[listcount] = id;
|
||||
printf("%2d) %s\n", listcount + 1, text);
|
||||
listcount++;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** End list code.
|
||||
**/
|
||||
|
||||
typedef struct MENU {
|
||||
char *text;
|
||||
void *action;
|
||||
int type; // 0 for menu, 1 for function.
|
||||
} MENU;
|
||||
|
||||
static void SetOC(void) {
|
||||
FCEUI_CheatSearchSetCurrentAsOriginal();
|
||||
}
|
||||
|
||||
static void UnhideEx(void) {
|
||||
FCEUI_CheatSearchShowExcluded();
|
||||
}
|
||||
|
||||
static void ToggleCheat(int num) {
|
||||
printf("Cheat %d %sabled.\n", 1 + num,
|
||||
FCEUI_ToggleCheat(num) ? "en" : "dis");
|
||||
}
|
||||
|
||||
static void ModifyCheat(int num) {
|
||||
char *name;
|
||||
char buf[256];
|
||||
uint32 A;
|
||||
uint8 V;
|
||||
int compare;
|
||||
int type;
|
||||
|
||||
int s;
|
||||
int t;
|
||||
|
||||
FCEUI_GetCheat(num, &name, &A, &V, &compare, &s, &type);
|
||||
|
||||
printf("Name [%s]: ", name);
|
||||
GetString(buf, 256);
|
||||
|
||||
/* This obviously doesn't allow for cheats with no names. Bah. Who wants
|
||||
nameless cheats anyway...
|
||||
*/
|
||||
|
||||
if (buf[0])
|
||||
name = buf; // Change name when FCEUI_SetCheat() is called.
|
||||
else
|
||||
name = 0; // Don't change name when FCEUI_SetCheat() is called.
|
||||
|
||||
printf("Address [$%04x]: ", (unsigned int)A);
|
||||
A = GetH16(A);
|
||||
|
||||
printf("Value [%03d]: ", (unsigned int)V);
|
||||
V = Get8(V);
|
||||
|
||||
printf("Compare [%3d]: ", compare);
|
||||
compare = GetI(compare);
|
||||
|
||||
printf("Type(0=Old Style, 1=Read Substitute) [%1d]: ", type);
|
||||
type = GetI(type) ? 1 : 0;
|
||||
|
||||
printf("Enable [%s]: ", s ? "Y" : "N");
|
||||
t = getchar();
|
||||
if (t == 'Y' || t == 'y') s = 1;
|
||||
else if (t == 'N' || t == 'n') s = 0;
|
||||
|
||||
FCEUI_SetCheat(num, name, A, V, compare, s, type);
|
||||
}
|
||||
|
||||
|
||||
static void AddCheatGGPAR(int which) {
|
||||
uint16 A;
|
||||
uint8 V;
|
||||
int C;
|
||||
int type;
|
||||
char name[256], code[256];
|
||||
|
||||
printf("Name: ");
|
||||
GetString(name, 256);
|
||||
|
||||
printf("Code: ");
|
||||
GetString(code, 256);
|
||||
|
||||
printf("Add cheat \"%s\" for code \"%s\"?", name, code);
|
||||
if (GetYN(0)) {
|
||||
if (which) {
|
||||
if (!FCEUI_DecodePAR(code, &A, &V, &C, &type)) {
|
||||
puts("Invalid Game Genie code.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!FCEUI_DecodeGG(code, &A, &V, &C)) {
|
||||
puts("Invalid Game Genie code.");
|
||||
return;
|
||||
}
|
||||
type = 1;
|
||||
}
|
||||
|
||||
if (FCEUI_AddCheat(name, A, V, C, type))
|
||||
puts("Cheat added.");
|
||||
else
|
||||
puts("Error adding cheat.");
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCheatGG(void) {
|
||||
AddCheatGGPAR(0);
|
||||
}
|
||||
|
||||
static void AddCheatPAR(void) {
|
||||
AddCheatGGPAR(1);
|
||||
}
|
||||
|
||||
static void AddCheatParam(uint32 A, uint8 V) {
|
||||
char name[256];
|
||||
|
||||
printf("Name: ");
|
||||
GetString(name, 256);
|
||||
printf("Address [$%04x]: ", (unsigned int)A);
|
||||
A = GetH16(A);
|
||||
printf("Value [%03d]: ", (unsigned int)V);
|
||||
V = Get8(V);
|
||||
printf("Add cheat \"%s\" for address $%04x with value %03d?", name, (unsigned int)A, (unsigned int)V);
|
||||
if (GetYN(0)) {
|
||||
if (FCEUI_AddCheat(name, A, V, -1, 0))
|
||||
puts("Cheat added.");
|
||||
else
|
||||
puts("Error adding cheat.");
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCheat(void) {
|
||||
AddCheatParam(0, 0);
|
||||
}
|
||||
|
||||
static int lid;
|
||||
static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data) {
|
||||
char tmp[512];
|
||||
int ret;
|
||||
|
||||
if (compare >= 0)
|
||||
sprintf(tmp, "%s $%04x:%03d:%03d - %s", s ? "*" : " ", (unsigned int)a, (unsigned int)v, compare, name);
|
||||
else
|
||||
sprintf(tmp, "%s $%04x:%03d - %s", s ? "*" : " ", (unsigned int)a, (unsigned int)v, name);
|
||||
if (type == 1)
|
||||
tmp[2] = 'S';
|
||||
ret = AddToList(tmp, lid);
|
||||
lid++;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void ListCheats(void) {
|
||||
int which;
|
||||
lid = 0;
|
||||
|
||||
BeginListShow();
|
||||
FCEUI_ListCheats(clistcallb, 0);
|
||||
which = EndListShow();
|
||||
if (which >= 0) {
|
||||
char tmp[32];
|
||||
printf(" <(T)oggle status, (M)odify, or (D)elete this cheat.> ");
|
||||
fgets(tmp, 32, stdin);
|
||||
switch (tolower(tmp[0])) {
|
||||
case 't': ToggleCheat(which);
|
||||
break;
|
||||
case 'd': if (!FCEUI_DelCheat(which))
|
||||
puts("Error deleting cheat!");
|
||||
else
|
||||
puts("Cheat has been deleted.");
|
||||
break;
|
||||
case 'm': ModifyCheat(which);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ResetSearch(void) {
|
||||
FCEUI_CheatSearchBegin();
|
||||
puts("Done.");
|
||||
}
|
||||
|
||||
static int srescallb(uint32 a, uint8 last, uint8 current, void *data) {
|
||||
char tmp[13];
|
||||
sprintf(tmp, "$%04x:%03d:%03d", (unsigned int)a, (unsigned int)last, (unsigned int)current);
|
||||
return(AddToList(tmp, a));
|
||||
}
|
||||
|
||||
static void ShowRes(void) {
|
||||
int n = FCEUI_CheatSearchGetCount();
|
||||
printf(" %d results:\n", n);
|
||||
if (n) {
|
||||
int which;
|
||||
BeginListShow();
|
||||
FCEUI_CheatSearchGet(srescallb, 0);
|
||||
which = EndListShow();
|
||||
if (which >= 0)
|
||||
AddCheatParam(which, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int ShowShortList(char *moe[], int n, int def) {
|
||||
int x, c;
|
||||
unsigned int baa;
|
||||
char tmp[16];
|
||||
|
||||
red:
|
||||
for (x = 0; x < n; x++)
|
||||
printf("%d) %s\n", x + 1, moe[x]);
|
||||
puts("D) Display List");
|
||||
clo:
|
||||
|
||||
printf("\nSelection [%d]> ", def + 1);
|
||||
fgets(tmp, 256, stdin);
|
||||
if (tmp[0] == '\n')
|
||||
return def;
|
||||
c = tolower(tmp[0]);
|
||||
baa = c - '1';
|
||||
|
||||
if (baa < n)
|
||||
return baa;
|
||||
else if (c == 'd')
|
||||
goto red;
|
||||
else {
|
||||
puts("Invalid selection.");
|
||||
goto clo;
|
||||
}
|
||||
}
|
||||
|
||||
static void DoSearch(void) {
|
||||
static int v1 = 0, v2 = 0;
|
||||
static int method = 0;
|
||||
char *m[6] = { "O==V1 && C==V2", "O==V1 && |O-C|==V2", "|O-C|==V2", "O!=C", "Value decreased", "Value increased" };
|
||||
printf("\nSearch Filter:\n");
|
||||
|
||||
method = ShowShortList(m, 6, method);
|
||||
if (method <= 1) {
|
||||
printf("V1 [%03d]: ", v1);
|
||||
v1 = Get8(v1);
|
||||
}
|
||||
if (method <= 2) {
|
||||
printf("V2 [%03d]: ", v2);
|
||||
v2 = Get8(v2);
|
||||
}
|
||||
FCEUI_CheatSearchEnd(method, v1, v2);
|
||||
puts("Search completed.\n");
|
||||
}
|
||||
|
||||
|
||||
static MENU NewCheatsMenu[] = {
|
||||
{ "Add Cheat", (void*)AddCheat, 1 },
|
||||
{ "Reset Search", (void*)ResetSearch, 1 },
|
||||
{ "Do Search", (void*)DoSearch, 1 },
|
||||
{ "Set Original to Current", (void*)SetOC, 1 },
|
||||
{ "Unhide Excluded", (void*)UnhideEx, 1 },
|
||||
{ "Show Results", (void*)ShowRes, 1 },
|
||||
{ "Add Game Genie Cheat", (void*)AddCheatGG, 1 },
|
||||
{ "Add PAR Cheat", (void*)AddCheatPAR, 1 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static MENU MainMenu[] = {
|
||||
{ "List Cheats", (void*)ListCheats, 1 },
|
||||
{ "New Cheats...", (void*)NewCheatsMenu, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void DoMenu(MENU *men) {
|
||||
int x = 0;
|
||||
|
||||
redisplay:
|
||||
x = 0;
|
||||
puts("");
|
||||
while (men[x].text) {
|
||||
printf("%d) %s\n", x + 1, men[x].text);
|
||||
x++;
|
||||
}
|
||||
puts("D) Display Menu\nX) Return to Previous\n");
|
||||
{
|
||||
char buf[32];
|
||||
int c;
|
||||
|
||||
recommand:
|
||||
printf("Command> ");
|
||||
fgets(buf, 32, stdin);
|
||||
c = tolower(buf[0]);
|
||||
if (c == '\n')
|
||||
goto recommand;
|
||||
else if (c == 'd')
|
||||
goto redisplay;
|
||||
else if (c == 'x') {
|
||||
return;
|
||||
} else if (sscanf(buf, "%d", &c)) {
|
||||
if (c > x) goto invalid;
|
||||
if (men[c - 1].type) {
|
||||
void (*func)(void) = (void (*)())men[c - 1].action;
|
||||
func();
|
||||
} else
|
||||
DoMenu((MENU*)men[c - 1].action); /* Mmm...recursivey goodness. */
|
||||
goto redisplay;
|
||||
} else {
|
||||
invalid:
|
||||
puts("Invalid command.\n");
|
||||
goto recommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoConsoleCheatConfig(void) {
|
||||
MENU *curmenu = MainMenu;
|
||||
|
||||
DoMenu(curmenu);
|
||||
}
|
||||
21
src/drivers/common/cheat.h
Normal file
21
src/drivers/common/cheat.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
void DoConsoleCheatConfig(void);
|
||||
134
src/drivers/common/config.c
Normal file
134
src/drivers/common/config.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains routines for reading/writing the */
|
||||
/* configuration file. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../fceu-types.h"
|
||||
#include "config.h"
|
||||
|
||||
static int FReadString(FILE *fp, char *str, int n) {
|
||||
int x = 0, z;
|
||||
for (;; ) {
|
||||
z = fgetc(fp);
|
||||
str[x] = z;
|
||||
x++;
|
||||
if (z <= 0) break;
|
||||
if (x >= n) return 0;
|
||||
}
|
||||
if (z < 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void GetValueR(FILE *fp, char *str, void *v, int c) {
|
||||
char buf[256];
|
||||
int s;
|
||||
|
||||
while (FReadString(fp, buf, 256)) {
|
||||
fread(&s, 1, 4, fp);
|
||||
if (!strcmp(str, buf)) {
|
||||
if (!c) { // String, allocate some memory.
|
||||
if (!(*(char**)v = (char*)malloc(s)))
|
||||
goto gogl;
|
||||
fread(*(char**)v, 1, s, fp);
|
||||
continue;
|
||||
} else if (s > c || s < c) {
|
||||
gogl:
|
||||
fseek(fp, s, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
fread((uint8*)v, 1, c, fp);
|
||||
} else
|
||||
fseek(fp, s, SEEK_CUR);
|
||||
}
|
||||
fseek(fp, 4, SEEK_SET);
|
||||
}
|
||||
|
||||
static void SetValueR(FILE *fp, char *str, void *v, int c) {
|
||||
fwrite(str, 1, strlen(str) + 1, fp);
|
||||
fwrite((uint8*)&c, 1, 4, fp);
|
||||
fwrite((uint8*)v, 1, c, fp);
|
||||
}
|
||||
|
||||
static void SaveParse(CFGSTRUCT *cfgst, FILE *fp) {
|
||||
int x = 0;
|
||||
|
||||
while (cfgst[x].ptr) {
|
||||
if (!cfgst[x].name) { // Link to new config structure
|
||||
SaveParse((CFGSTRUCT*)cfgst[x].ptr, fp); // Recursion is sexy. I could
|
||||
// save a little stack space if I made
|
||||
// the file pointer a non-local
|
||||
// variable...
|
||||
x++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cfgst[x].len) // Plain data
|
||||
SetValueR(fp, cfgst[x].name, cfgst[x].ptr, cfgst[x].len);
|
||||
else // String
|
||||
if (*(char**)cfgst[x].ptr) // Only save it if there IS a string.
|
||||
SetValueR(fp, cfgst[x].name, *(char**)cfgst[x].ptr,
|
||||
strlen(*(char**)cfgst[x].ptr) + 1);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst) {
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(filename, "wb");
|
||||
if (fp == NULL) return;
|
||||
|
||||
SaveParse(cfgst, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void LoadParse(CFGSTRUCT *cfgst, FILE *fp) {
|
||||
int x = 0;
|
||||
|
||||
while (cfgst[x].ptr) {
|
||||
if (!cfgst[x].name) { // Link to new config structure
|
||||
LoadParse((CFGSTRUCT*)cfgst[x].ptr, fp);
|
||||
x++;
|
||||
continue;
|
||||
}
|
||||
GetValueR(fp, cfgst[x].name, cfgst[x].ptr, cfgst[x].len);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadFCEUConfig(char *filename, CFGSTRUCT *cfgst) {
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == NULL) return;
|
||||
LoadParse(cfgst, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
40
src/drivers/common/config.h
Normal file
40
src/drivers/common/config.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef _DRIVERS_CONFIGH
|
||||
typedef struct {
|
||||
char *name;
|
||||
void *ptr;
|
||||
int len;
|
||||
} CFGSTRUCT;
|
||||
|
||||
void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst);
|
||||
void LoadFCEUConfig(char *filename, CFGSTRUCT *cfgst);
|
||||
|
||||
/* Macros for building CFGSTRUCT structures. */
|
||||
|
||||
/* CFGSTRUCT structures must always end with ENDCFGSTRUCT */
|
||||
#define ENDCFGSTRUCT { 0, 0, 0 }
|
||||
|
||||
/* When this macro is used, the config loading/saving code will parse
|
||||
the new config structure until the end of it is detected, then it
|
||||
will continue parsing the original config structure.
|
||||
*/
|
||||
#define ADDCFGSTRUCT(x) { 0, &x, 0 }
|
||||
|
||||
/* Oops. The NAC* macros shouldn't have the # in front of the w, but
|
||||
fixing this would break configuration files of previous versions and it
|
||||
isn't really hurting much.
|
||||
*/
|
||||
|
||||
/* Single piece of data(integer). */
|
||||
#define AC(x) { # x, &x, sizeof(x) }
|
||||
#define NAC(w, x) { # w, &x, sizeof(x) }
|
||||
|
||||
/* Array. */
|
||||
#define ACA(x) { # x, x, sizeof(x) }
|
||||
#define NACA(w, x) { # w, x, sizeof(x) }
|
||||
|
||||
/* String(pointer) with automatic memory allocation. */
|
||||
#define ACS(x) { # x, &x, 0 }
|
||||
#define NACS(w, x) { # w, &x, 0 }
|
||||
|
||||
#define _DRIVERS_CONFIGH
|
||||
#endif
|
||||
2434
src/drivers/common/hq2x.c
Normal file
2434
src/drivers/common/hq2x.c
Normal file
File diff suppressed because it is too large
Load Diff
4
src/drivers/common/hq2x.h
Normal file
4
src/drivers/common/hq2x.h
Normal file
@@ -0,0 +1,4 @@
|
||||
void hq2x_32(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL);
|
||||
int hq2x_InitLUTs(void);
|
||||
void hq2x_Kill(void);
|
||||
|
||||
3318
src/drivers/common/hq3x.c
Normal file
3318
src/drivers/common/hq3x.c
Normal file
File diff suppressed because it is too large
Load Diff
4
src/drivers/common/hq3x.h
Normal file
4
src/drivers/common/hq3x.h
Normal file
@@ -0,0 +1,4 @@
|
||||
void hq3x_32(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL);
|
||||
int hq3x_InitLUTs(void);
|
||||
void hq3x_Kill(void);
|
||||
|
||||
911
src/drivers/common/scale2x.c
Normal file
911
src/drivers/common/scale2x.c
Normal file
@@ -0,0 +1,911 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a C and MMX implementation of the Scale2x effect.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "scale2x.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale2x C implementation */
|
||||
|
||||
static inline void scale2x_8_def_single(scale2x_uint8* __restrict__ dst, const scale2x_uint8* __restrict__ src0, const scale2x_uint8* __restrict__ src1, const scale2x_uint8* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale2x_16_def_single(scale2x_uint16* __restrict__ dst, const scale2x_uint16* __restrict__ src0, const scale2x_uint16* __restrict__ src1, const scale2x_uint16* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale2x_32_def_single(scale2x_uint32* __restrict__ dst, const scale2x_uint32* __restrict__ src0, const scale2x_uint32* __restrict__ src1, const scale2x_uint32* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 8 bits.
|
||||
* The function is implemented in C.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_8_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_8_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 16 bits.
|
||||
* This function operates like scale2x_8_def() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_16_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_16_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 32 bits.
|
||||
* This function operates like scale2x_8_def() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_32_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_32_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale2x MMX implementation */
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
/*
|
||||
* Apply the Scale2x effect at a single row.
|
||||
* This function must be called only by the other scale2x functions.
|
||||
*
|
||||
* Considering the pixel map :
|
||||
*
|
||||
* ABC (src0)
|
||||
* DEF (src1)
|
||||
* GHI (src2)
|
||||
*
|
||||
* this functions compute 2 new pixels in substitution of the source pixel E
|
||||
* like this map :
|
||||
*
|
||||
* ab (dst)
|
||||
*
|
||||
* with these variables :
|
||||
*
|
||||
* ¤t -> E
|
||||
* ¤t_left -> D
|
||||
* ¤t_right -> F
|
||||
* ¤t_upper -> B
|
||||
* ¤t_lower -> H
|
||||
*
|
||||
* %0 -> current_upper
|
||||
* %1 -> current
|
||||
* %2 -> current_lower
|
||||
* %3 -> dst
|
||||
* %4 -> counter
|
||||
*
|
||||
* %mm0 -> *current_left
|
||||
* %mm1 -> *current_next
|
||||
* %mm2 -> tmp0
|
||||
* %mm3 -> tmp1
|
||||
* %mm4 -> tmp2
|
||||
* %mm5 -> tmp3
|
||||
* %mm6 -> *current_upper
|
||||
* %mm7 -> *current
|
||||
*/
|
||||
static inline void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) {
|
||||
assert(count >= 16);
|
||||
assert(count % 8 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2 * 8;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $3, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $56, %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) {
|
||||
assert(count >= 8);
|
||||
assert(count % 4 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2 * 4;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $2, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $48, %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) {
|
||||
assert(count >= 4);
|
||||
assert(count % 2 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2 * 2;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $1, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $32, %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 8 bits.
|
||||
* This is a very fast MMX implementation.
|
||||
* The implementation uses a combination of cmp/and/not operations to
|
||||
* completly remove the need of conditional jumps. This trick give the
|
||||
* major speed improvement.
|
||||
* Also, using the 8 bytes MMX registers more than one pixel are computed
|
||||
* at the same time.
|
||||
* Before calling this function you must ensure that the currenct CPU supports
|
||||
* the MMX instruction set. After calling it you must be sure to call the EMMS
|
||||
* instruction before any floating-point operation.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 16 and a multiple of 8.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) {
|
||||
if (count % 8 != 0 || count < 16) {
|
||||
scale2x_8_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 16);
|
||||
assert(count % 8 == 0);
|
||||
|
||||
scale2x_8_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_8_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 16 bits.
|
||||
* This function operates like scale2x_8_mmx() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 8 and a multiple of 4.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) {
|
||||
if (count % 4 != 0 || count < 8) {
|
||||
scale2x_16_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 8);
|
||||
assert(count % 4 == 0);
|
||||
|
||||
scale2x_16_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_16_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 32 bits.
|
||||
* This function operates like scale2x_8_mmx() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 4 and a multiple of 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) {
|
||||
if (count % 2 != 0 || count < 4) {
|
||||
scale2x_32_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 4);
|
||||
assert(count % 2 == 0);
|
||||
|
||||
scale2x_32_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_32_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
51
src/drivers/common/scale2x.h
Normal file
51
src/drivers/common/scale2x.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SCALE2X_H
|
||||
#define __SCALE2X_H
|
||||
|
||||
typedef unsigned char scale2x_uint8;
|
||||
typedef unsigned short scale2x_uint16;
|
||||
typedef unsigned scale2x_uint32;
|
||||
|
||||
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
/**
|
||||
* End the use of the MMX instructions.
|
||||
* This function must be called before using any floating-point operations.
|
||||
*/
|
||||
static inline void scale2x_mmx_emms(void) {
|
||||
__asm__ __volatile__ (
|
||||
"emms"
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
373
src/drivers/common/scale3x.c
Normal file
373
src/drivers/common/scale3x.c
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a C and MMX implementation of the Scale2x effect.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "scale3x.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale3x C implementation */
|
||||
|
||||
static inline void scale3x_8_def_border(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_8_def_center(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_16_def_border(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_16_def_center(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_32_def_border(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_32_def_center(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 8 bits.
|
||||
* The function is implemented in C.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_8_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_8_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_8_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 16 bits.
|
||||
* This function operates like scale3x_8_def() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_16_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_16_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_16_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 32 bits.
|
||||
* This function operates like scale3x_8_def() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) {
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_32_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_32_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_32_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
33
src/drivers/common/scale3x.h
Normal file
33
src/drivers/common/scale3x.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SCALE3X_H
|
||||
#define __SCALE3X_H
|
||||
|
||||
typedef unsigned char scale3x_uint8;
|
||||
typedef unsigned short scale3x_uint16;
|
||||
typedef unsigned scale3x_uint32;
|
||||
|
||||
void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count);
|
||||
void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count);
|
||||
void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count);
|
||||
|
||||
#endif
|
||||
|
||||
376
src/drivers/common/scalebit.c
Normal file
376
src/drivers/common/scalebit.c
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2003 Andrea Mazzoleni
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains an example implementation of the Scale effect
|
||||
* applyed to a generic bitmap.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "scale2x.h"
|
||||
#include "scale3x.h"
|
||||
|
||||
#if HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Apply the Scale2x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) {
|
||||
switch (pixel) {
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
case 1: scale2x_8_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 2: scale2x_16_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 4: scale2x_32_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
#else
|
||||
case 1: scale2x_8_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 2: scale2x_16_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 4: scale2x_32_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale3x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) {
|
||||
switch (pixel) {
|
||||
case 1: scale3x_8_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
case 2: scale3x_16_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
case 4: scale3x_32_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row) {
|
||||
stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);
|
||||
stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);
|
||||
}
|
||||
|
||||
#define SCDST(i) (dst + (i) * dst_slice)
|
||||
#define SCSRC(i) (src + (i) * src_slice)
|
||||
#define SCMID(i) (mid[(i)])
|
||||
|
||||
/**
|
||||
* Apply the Scale2x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 2x2 times the size of the source bitmap.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
|
||||
assert(height >= 2);
|
||||
|
||||
count = height;
|
||||
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
|
||||
dst = SCDST(2);
|
||||
|
||||
count -= 2;
|
||||
while (count) {
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
|
||||
dst = SCDST(2);
|
||||
src = SCSRC(1);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(1 - 1), SCSRC(2 - 1), SCSRC(2 - 1), pixel, width);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
scale2x_mmx_emms();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale32x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 3x3 times the size of the source bitmap.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
|
||||
assert(height >= 2);
|
||||
|
||||
count = height;
|
||||
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
|
||||
dst = SCDST(3);
|
||||
|
||||
count -= 2;
|
||||
while (count) {
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
|
||||
dst = SCDST(3);
|
||||
src = SCSRC(1);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(1 - 1), SCSRC(2 - 1), SCSRC(2 - 1), pixel, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 4x4 times the size of the source bitmap.
|
||||
* \note This function requires also a small buffer bitmap used internally to store
|
||||
* intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,
|
||||
* and a vertical size of 6 rows. The memory of this buffer must not be allocated
|
||||
* in video memory because it's also read and not only written. Generally
|
||||
* a heap (malloc) or a stack (alloca) buffer is the best choices.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_mid Pointer at the first pixel of the buffer bitmap.
|
||||
* \param mid_slice Size in bytes of a buffer bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
unsigned char* mid[6];
|
||||
|
||||
assert(height >= 4);
|
||||
|
||||
count = height;
|
||||
|
||||
/* set the 6 buffer pointers */
|
||||
mid[0] = (unsigned char*)void_mid;
|
||||
mid[1] = mid[0] + mid_slice;
|
||||
mid[2] = mid[1] + mid_slice;
|
||||
mid[3] = mid[2] + mid_slice;
|
||||
mid[4] = mid[3] + mid_slice;
|
||||
mid[5] = mid[4] + mid_slice;
|
||||
|
||||
stage_scale2x(SCMID(-2 + 6), SCMID(-1 + 6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2 + 6), SCMID(-2 + 6), SCMID(-1 + 6), SCMID(0), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1 + 6), SCMID(0), SCMID(1), SCMID(2), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
count -= 4;
|
||||
while (count) {
|
||||
unsigned char* tmp;
|
||||
|
||||
stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
src = SCSRC(1);
|
||||
|
||||
tmp = SCMID(0); /* shift by 2 position */
|
||||
SCMID(0) = SCMID(2);
|
||||
SCMID(2) = SCMID(4);
|
||||
SCMID(4) = tmp;
|
||||
tmp = SCMID(1);
|
||||
SCMID(1) = SCMID(3);
|
||||
SCMID(3) = SCMID(5);
|
||||
SCMID(5) = tmp;
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
scale2x_mmx_emms();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 4x4 times the size of the source bitmap.
|
||||
* \note This function operates like ::scale4x_buf() but the intermediate buffer is
|
||||
* automatically allocated in the stack.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
unsigned mid_slice;
|
||||
void* mid;
|
||||
|
||||
mid_slice = 2 * pixel * width; /* required space for 1 row buffer */
|
||||
|
||||
mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */
|
||||
|
||||
#if HAVE_ALLOCA
|
||||
mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */
|
||||
|
||||
assert(mid != 0); /* alloca should never fails */
|
||||
#else
|
||||
mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */
|
||||
|
||||
if (!mid)
|
||||
return;
|
||||
#endif
|
||||
|
||||
scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);
|
||||
|
||||
#if !HAVE_ALLOCA
|
||||
free(mid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the scale implementation is applicable at the given arguments.
|
||||
* \param scale Scale factor. 2, 3 or 4.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
* \return
|
||||
* - -1 on precondition violated.
|
||||
* - 0 on success.
|
||||
*/
|
||||
int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height) {
|
||||
if (scale != 2 && scale != 3 && scale != 4)
|
||||
return -1;
|
||||
|
||||
if (pixel != 1 && pixel != 2 && pixel != 4)
|
||||
return -1;
|
||||
|
||||
switch (scale) {
|
||||
case 2:
|
||||
case 3:
|
||||
if (height < 2)
|
||||
return -1;
|
||||
break;
|
||||
case 4:
|
||||
if (height < 4)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
switch (scale) {
|
||||
case 2:
|
||||
case 4:
|
||||
if (width < (16 / pixel))
|
||||
return -1;
|
||||
if (width % (8 / pixel) != 0)
|
||||
return -1;
|
||||
break;
|
||||
case 3:
|
||||
if (width < 2)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (width < 2)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale effect on a bitmap.
|
||||
* This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().
|
||||
* \param scale Scale factor. 2, 3 or 4.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
switch (scale) {
|
||||
case 2:
|
||||
scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
case 3:
|
||||
scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
case 4:
|
||||
scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
43
src/drivers/common/scalebit.h
Normal file
43
src/drivers/common/scalebit.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2003 Andrea Mazzoleni
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains an example implementation of the Scale effect
|
||||
* applyed to a generic bitmap.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#ifndef __SCALEBIT_H
|
||||
#define __SCALEBIT_H
|
||||
|
||||
int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height);
|
||||
void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height);
|
||||
|
||||
#endif
|
||||
|
||||
726
src/drivers/common/vidblit.c
Normal file
726
src/drivers/common/vidblit.c
Normal file
@@ -0,0 +1,726 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "scalebit.h"
|
||||
#include "hq2x.h"
|
||||
#include "hq3x.h"
|
||||
|
||||
#include "../../fceu-types.h"
|
||||
|
||||
static uint32 CBM[3];
|
||||
static uint32 *palettetranslate = 0;
|
||||
|
||||
static uint16 *specbuf = NULL; // 8bpp -> 16bpp, pre hq2x/hq3x
|
||||
static uint32 *specbuf32bpp = NULL; // Buffer to hold output
|
||||
// of hq2x/hq3x when converting
|
||||
// to 16bpp and 24bpp
|
||||
static int backBpp, backshiftr[3], backshiftl[3];
|
||||
//static uint32 backmask[3];
|
||||
|
||||
static uint8 *specbuf8bpp = NULL; // For 2xscale, 3xscale.
|
||||
|
||||
|
||||
static int silt;
|
||||
|
||||
static int Bpp; // BYTES per pixel
|
||||
static int highefx;
|
||||
|
||||
#define BLUR_RED 20
|
||||
#define BLUR_GREEN 20
|
||||
#define BLUR_BLUE 10
|
||||
|
||||
#define FVB_SCANLINES 1
|
||||
|
||||
/* The blur effect is only available for bpp>=16. It could be easily modified
|
||||
to look like what happens on the real NES and TV, but lack of decent
|
||||
synchronization to the vertical retrace period makes it look rather
|
||||
blah.
|
||||
*/
|
||||
#define FVB_BLUR 2
|
||||
|
||||
static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl) {
|
||||
int a, x, z, y;
|
||||
cshiftl[0] = cshiftl[1] = cshiftl[2] = -1;
|
||||
for (a = 0; a < 3; a++) {
|
||||
for (x = 0, y = -1, z = 0; x < 32; x++) {
|
||||
if (CBM[a] & (1 << x)) {
|
||||
if (cshiftl[a] == -1) cshiftl[a] = x;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
cshiftr[a] = (8 - z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int specfilt) {
|
||||
if (specfilt == 2 || specfilt == 4) { // scale2x and scale3x
|
||||
int multi;
|
||||
|
||||
if (specfilt == 2) multi = 2 * 2;
|
||||
else multi = 3 * 3;
|
||||
|
||||
specbuf8bpp = malloc(256 * 240 * multi);
|
||||
} else if (specfilt == 1 || specfilt == 3) { // hq2x and hq3x
|
||||
if (b == 1)
|
||||
return(0);
|
||||
|
||||
if (b == 2 || b == 3) { // 8->16->(hq2x)->32-> 24 or 16. YARGH.
|
||||
uint32 tmpCBM[3];
|
||||
backBpp = b;
|
||||
tmpCBM[0] = rmask;
|
||||
tmpCBM[1] = gmask;
|
||||
tmpCBM[2] = bmask;
|
||||
|
||||
CalculateShift(tmpCBM, backshiftr, backshiftl);
|
||||
|
||||
if (b == 2) {
|
||||
// ark
|
||||
backshiftr[0] += 16;
|
||||
backshiftr[1] += 8;
|
||||
backshiftr[2] += 0;
|
||||
|
||||
// Begin iffy code(requires 16bpp and 32bpp to have same RGB order)
|
||||
//backmask[0] = (rmask>>backshiftl[0]) << (backshiftr[0]);
|
||||
//backmask[1] = (gmask>>backshiftl[1]) << (backshiftr[1]);
|
||||
//backmask[2] = (bmask>>backshiftl[2]) << (backshiftr[2]);
|
||||
|
||||
//int x;
|
||||
//for(x=0;x<3;x++)
|
||||
// backshiftr[x] -= backshiftl[x];
|
||||
// End iffy code
|
||||
}
|
||||
if (specfilt == 1) specbuf32bpp = malloc(256 * 240 * 4 * sizeof(uint32));
|
||||
else if (specfilt == 3) specbuf32bpp = malloc(256 * 240 * 9 * sizeof(uint32));
|
||||
}
|
||||
|
||||
efx = 0;
|
||||
b = 2;
|
||||
rmask = 0x1F << 11;
|
||||
gmask = 0x3F << 5;
|
||||
bmask = 0x1F;
|
||||
|
||||
if (specfilt == 3)
|
||||
hq3x_InitLUTs();
|
||||
else
|
||||
hq2x_InitLUTs();
|
||||
|
||||
specbuf = malloc(256 * 240 * sizeof(uint16));
|
||||
}
|
||||
|
||||
silt = specfilt;
|
||||
|
||||
Bpp = b;
|
||||
|
||||
highefx = efx;
|
||||
|
||||
if (Bpp <= 1 || Bpp > 4)
|
||||
return(0);
|
||||
|
||||
if (efx & FVB_BLUR) {
|
||||
if (Bpp == 2)
|
||||
palettetranslate = (uint32*)malloc(65536 * 4);
|
||||
else if (Bpp >= 3)
|
||||
palettetranslate = (uint32*)malloc(65536 * 4);
|
||||
} else {
|
||||
if (Bpp == 2)
|
||||
palettetranslate = (uint32*)malloc(65536 * 4);
|
||||
else if (Bpp >= 3)
|
||||
palettetranslate = (uint32*)malloc(256 * 4);
|
||||
}
|
||||
|
||||
if (!palettetranslate)
|
||||
return(0);
|
||||
|
||||
|
||||
CBM[0] = rmask;
|
||||
CBM[1] = gmask;
|
||||
CBM[2] = bmask;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void KillBlitToHigh(void) {
|
||||
if (palettetranslate) {
|
||||
free(palettetranslate);
|
||||
palettetranslate = NULL;
|
||||
}
|
||||
|
||||
if (specbuf8bpp) {
|
||||
free(specbuf8bpp);
|
||||
specbuf8bpp = NULL;
|
||||
}
|
||||
if (specbuf32bpp) {
|
||||
free(specbuf32bpp);
|
||||
specbuf32bpp = NULL;
|
||||
}
|
||||
if (specbuf) {
|
||||
if (silt == 3)
|
||||
hq3x_Kill();
|
||||
else
|
||||
hq2x_Kill();
|
||||
specbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetPaletteBlitToHigh(uint8 *src) {
|
||||
int cshiftr[3];
|
||||
int cshiftl[3];
|
||||
int x, y;
|
||||
|
||||
CalculateShift(CBM, cshiftr, cshiftl);
|
||||
|
||||
switch (Bpp) {
|
||||
case 2:
|
||||
if (highefx & FVB_BLUR) {
|
||||
for (x = 0; x < 256; x++) {
|
||||
uint32 r, g, b;
|
||||
for (y = 0; y < 256; y++) {
|
||||
r = src[x << 2] * (100 - BLUR_RED);
|
||||
g = src[(x << 2) + 1] * (100 - BLUR_GREEN);
|
||||
b = src[(x << 2) + 2] * (100 - BLUR_BLUE);
|
||||
|
||||
r += src[y << 2] * BLUR_RED;
|
||||
g += src[(y << 2) + 1] * BLUR_GREEN;
|
||||
b += src[(y << 2) + 2] * BLUR_BLUE;
|
||||
r /= 100;
|
||||
g /= 100;
|
||||
b /= 100;
|
||||
|
||||
if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
|
||||
palettetranslate[x | (y << 8)] = ((r >> cshiftr[0]) << cshiftl[0]) |
|
||||
((g >> cshiftr[1]) << cshiftl[1]) |
|
||||
((b >> cshiftr[2]) << cshiftl[2]);
|
||||
}
|
||||
}
|
||||
} else
|
||||
for (x = 0; x < 65536; x++) {
|
||||
uint16 lower, upper;
|
||||
|
||||
lower = (src[((x & 255) << 2)] >> cshiftr[0]) << cshiftl[0];
|
||||
lower |= (src[((x & 255) << 2) + 1] >> cshiftr[1]) << cshiftl[1];
|
||||
lower |= (src[((x & 255) << 2) + 2] >> cshiftr[2]) << cshiftl[2];
|
||||
upper = (src[((x >> 8) << 2)] >> cshiftr[0]) << cshiftl[0];
|
||||
upper |= (src[((x >> 8) << 2) + 1] >> cshiftr[1]) << cshiftl[1];
|
||||
upper |= (src[((x >> 8) << 2) + 2] >> cshiftr[2]) << cshiftl[2];
|
||||
|
||||
palettetranslate[x] = lower | (upper << 16);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
for (x = 0; x < 256; x++) {
|
||||
uint32 r, g, b;
|
||||
|
||||
if (!(highefx & FVB_BLUR)) {
|
||||
r = src[x << 2];
|
||||
g = src[(x << 2) + 1];
|
||||
b = src[(x << 2) + 2];
|
||||
palettetranslate[x] = (r << cshiftl[0]) | (g << cshiftl[1]) | (b << cshiftl[2]);
|
||||
} else
|
||||
for (y = 0; y < 256; y++) {
|
||||
r = src[x << 2] * (100 - BLUR_RED);
|
||||
g = src[(x << 2) + 1] * (100 - BLUR_GREEN);
|
||||
b = src[(x << 2) + 2] * (100 - BLUR_BLUE);
|
||||
|
||||
r += src[y << 2] * BLUR_RED;
|
||||
g += src[(y << 2) + 1] * BLUR_GREEN;
|
||||
b += src[(y << 2) + 2] * BLUR_BLUE;
|
||||
|
||||
r /= 100;
|
||||
g /= 100;
|
||||
b /= 100;
|
||||
if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
|
||||
|
||||
palettetranslate[x | (y << 8)] = (r << cshiftl[0]) | (g << cshiftl[1]) | (b << cshiftl[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit32to24(uint32 *src, uint8 *dest, int xr, int yr, int dpitch) {
|
||||
int x, y;
|
||||
|
||||
for (y = yr; y; y--) {
|
||||
for (x = xr; x; x--) {
|
||||
uint32 tmp = *src;
|
||||
*dest = tmp;
|
||||
dest++;
|
||||
*dest = tmp >> 8;
|
||||
dest++;
|
||||
*dest = tmp >> 16;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
dest += dpitch / 3 - xr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Blit32to16(uint32 *src, uint16 *dest, int xr, int yr, int dpitch,
|
||||
int shiftr[3], int shiftl[3]) {
|
||||
int x, y;
|
||||
//printf("%d\n",shiftl[1]);
|
||||
for (y = yr; y; y--) {
|
||||
for (x = xr; x; x--) {
|
||||
uint32 tmp = *src;
|
||||
uint16 dtmp;
|
||||
|
||||
// Begin iffy code
|
||||
//dtmp = (tmp & backmask[2]) >> shiftr[2];
|
||||
//dtmp |= (tmp & backmask[1]) >> shiftr[1];
|
||||
//dtmp |= (tmp & backmask[0]) >> shiftr[0];
|
||||
// End iffy code
|
||||
|
||||
// Begin non-iffy code
|
||||
dtmp = ((tmp & 0x0000FF) >> shiftr[2]) << shiftl[2];
|
||||
dtmp |= ((tmp & 0x00FF00) >> shiftr[1]) << shiftl[1];
|
||||
dtmp |= ((tmp & 0xFF0000) >> shiftr[0]) << shiftl[0];
|
||||
// End non-iffy code
|
||||
|
||||
//dtmp = ((tmp&0x0000FF) >> 3);
|
||||
//dtmp |= ((tmp&0x00FC00) >>5);
|
||||
//dtmp |= ((tmp&0xF80000) >>8);
|
||||
|
||||
*dest = dtmp;
|
||||
src++;
|
||||
dest++;
|
||||
}
|
||||
dest += dpitch / 2 - xr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale, int efx, int special) {
|
||||
int x, y;
|
||||
int pinc;
|
||||
|
||||
if (special == 2) {
|
||||
if (xscale != 2 || yscale != 2) return;
|
||||
|
||||
scale(2, dest, pitch, src, 256, 1, xr, yr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (special == 4) {
|
||||
if (xscale != 3 || yscale != 3) return;
|
||||
scale(3, dest, pitch, src, 256, 1, xr, yr);
|
||||
return;
|
||||
}
|
||||
|
||||
pinc = pitch - (xr * xscale);
|
||||
if (xscale != 1 || yscale != 1) {
|
||||
if (efx & FVB_SCANLINES) {
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
int doo = yscale - (yscale >> 1);
|
||||
do {
|
||||
for (x = xr; x; x--, src++) {
|
||||
int too = xscale;
|
||||
do {
|
||||
*(uint8*)dest = *(uint8*)src;
|
||||
dest++;
|
||||
} while (--too);
|
||||
}
|
||||
src -= xr;
|
||||
dest += pinc;
|
||||
} while (--doo);
|
||||
//src-=xr*(yscale-(yscale>>1));
|
||||
dest += pitch * (yscale >> 1);
|
||||
|
||||
src += xr;
|
||||
}
|
||||
} else {
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
int doo = yscale;
|
||||
do {
|
||||
for (x = xr; x; x--, src++) {
|
||||
int too = xscale;
|
||||
do {
|
||||
*(uint8*)dest = *(uint8*)src;
|
||||
dest++;
|
||||
} while (--too);
|
||||
}
|
||||
src -= xr;
|
||||
dest += pinc;
|
||||
} while (--doo);
|
||||
src += xr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (y = yr; y; y--, dest += pinc, src += 256 - xr)
|
||||
for (x = xr; x; x -= 4, dest += 4, src += 4)
|
||||
*(uint32*)dest = *(uint32*)src;
|
||||
}
|
||||
}
|
||||
|
||||
/* Todo: Make sure 24bpp code works right with big-endian cpus */
|
||||
|
||||
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch,
|
||||
int xscale, int yscale) {
|
||||
int x, y;
|
||||
int pinc;
|
||||
uint8 *destbackup = NULL; /* For hq2x */
|
||||
int pitchbackup = 0;
|
||||
|
||||
//static int google=0;
|
||||
//google^=1;
|
||||
|
||||
if (specbuf8bpp) { // 2xscale/3xscale
|
||||
int mult;
|
||||
int base;
|
||||
|
||||
if (silt == 2) mult = 2;
|
||||
else mult = 3;
|
||||
|
||||
Blit8To8(src, specbuf8bpp, xr, yr, 256 * mult, xscale, yscale, 0, silt);
|
||||
|
||||
xr *= mult;
|
||||
yr *= mult;
|
||||
xscale = yscale = 1;
|
||||
src = specbuf8bpp;
|
||||
base = 256 * mult;
|
||||
|
||||
switch (Bpp) {
|
||||
case 4:
|
||||
pinc = pitch - (xr << 2);
|
||||
for (y = yr; y; y--, src += base - xr) {
|
||||
for (x = xr; x; x--) {
|
||||
*(uint32*)dest = palettetranslate[(uint32) * src];
|
||||
dest += 4;
|
||||
src++;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc = pitch - (xr + xr + xr);
|
||||
for (y = yr; y; y--, src += base - xr) {
|
||||
for (x = xr; x; x--) {
|
||||
uint32 tmp = palettetranslate[(uint32) * src];
|
||||
*(uint8*)dest = tmp;
|
||||
*((uint8*)dest + 1) = tmp >> 8;
|
||||
*((uint8*)dest + 2) = tmp >> 16;
|
||||
dest += 3;
|
||||
src++;
|
||||
src++;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc = pitch - (xr << 1);
|
||||
|
||||
for (y = yr; y; y--, src += base - xr) {
|
||||
for (x = xr >> 1; x; x--) {
|
||||
*(uint32*)dest = palettetranslate[*(uint16*)src];
|
||||
dest += 4;
|
||||
src += 2;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
} else if (specbuf) {
|
||||
destbackup = dest;
|
||||
dest = (uint8*)specbuf;
|
||||
pitchbackup = pitch;
|
||||
|
||||
pitch = xr * sizeof(uint16);
|
||||
xscale = 1;
|
||||
yscale = 1;
|
||||
}
|
||||
|
||||
if (highefx & FVB_BLUR) { // DONE
|
||||
if (xscale != 1 || yscale != 1 || (highefx & FVB_SCANLINES)) { // DONE
|
||||
switch (Bpp) {
|
||||
case 4:
|
||||
pinc = pitch - ((xr * xscale) << 2);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
int doo = yscale;
|
||||
|
||||
if (highefx & FVB_SCANLINES)
|
||||
doo -= yscale >> 1;
|
||||
do {
|
||||
uint8 last = 0x00;
|
||||
|
||||
//if(doo == 1 && google) dest+=4;
|
||||
for (x = xr; x; x--, src++) {
|
||||
int too = xscale;
|
||||
do {
|
||||
*(uint32*)dest = palettetranslate[*src | (last << 8)];
|
||||
dest += 4;
|
||||
} while (--too);
|
||||
last = *src;
|
||||
}
|
||||
//if(doo == 1 && google) dest-=4;
|
||||
src -= xr;
|
||||
dest += pinc;
|
||||
} while (--doo);
|
||||
src += xr;
|
||||
if (highefx & FVB_SCANLINES)
|
||||
dest += pitch * (yscale >> 1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc = pitch - ((xr * xscale) * 3);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
int doo = yscale;
|
||||
|
||||
if (highefx & FVB_SCANLINES)
|
||||
doo -= yscale >> 1;
|
||||
do {
|
||||
uint8 last = 0x00;
|
||||
for (x = xr; x; x--, src++) {
|
||||
int too = xscale;
|
||||
do {
|
||||
*(uint32*)dest = palettetranslate[*src | (last << 8)];
|
||||
dest += 3;
|
||||
} while (--too);
|
||||
last = *src;
|
||||
}
|
||||
src -= xr;
|
||||
dest += pinc;
|
||||
} while (--doo);
|
||||
src += xr;
|
||||
if (highefx & FVB_SCANLINES)
|
||||
dest += pitch * (yscale >> 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pinc = pitch - ((xr * xscale) << 1);
|
||||
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
int doo = yscale;
|
||||
|
||||
if (highefx & FVB_SCANLINES)
|
||||
doo -= yscale >> 1;
|
||||
do {
|
||||
uint8 last = 0x00;
|
||||
for (x = xr; x; x--, src++) {
|
||||
int too = xscale;
|
||||
do {
|
||||
*(uint16*)dest = palettetranslate[*src | (last << 8)];
|
||||
dest += 2;
|
||||
} while (--too);
|
||||
last = *src;
|
||||
}
|
||||
src -= xr;
|
||||
dest += pinc;
|
||||
} while (--doo);
|
||||
src += xr;
|
||||
if (highefx & FVB_SCANLINES)
|
||||
dest += pitch * (yscale >> 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else // No scaling, no scanlines, just blurring. - DONE
|
||||
switch (Bpp) {
|
||||
case 4:
|
||||
pinc = pitch - (xr << 2);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
uint8 last = 0x00;
|
||||
for (x = xr; x; x--) {
|
||||
*(uint32*)dest = palettetranslate[*src | (last << 8)];
|
||||
last = *src;
|
||||
dest += 4;
|
||||
src++;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc = pitch - (xr + xr + xr);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
uint8 last = 0x00;
|
||||
for (x = xr; x; x--) {
|
||||
uint32 tmp = palettetranslate[*src | (last << 8)];
|
||||
last = *src;
|
||||
*(uint8*)dest = tmp;
|
||||
*((uint8*)dest + 1) = tmp >> 8;
|
||||
*((uint8*)dest + 2) = tmp >> 16;
|
||||
dest += 3;
|
||||
src++;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc = pitch - (xr << 1);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
uint8 last = 0x00;
|
||||
for (x = xr; x; x--) {
|
||||
*(uint16*)dest = palettetranslate[*src | (last << 8)];
|
||||
last = *src;
|
||||
dest += 2;
|
||||
src++;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else { // No blur effects.
|
||||
if (xscale != 1 || yscale != 1 || (highefx & FVB_SCANLINES)) {
|
||||
switch (Bpp) {
|
||||
case 4:
|
||||
pinc = pitch - ((xr * xscale) << 2);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
int doo = yscale;
|
||||
|
||||
if (highefx & FVB_SCANLINES)
|
||||
doo -= yscale >> 1;
|
||||
do {
|
||||
for (x = xr; x; x--, src++) {
|
||||
int too = xscale;
|
||||
do {
|
||||
*(uint32*)dest = palettetranslate[*src];
|
||||
dest += 4;
|
||||
} while (--too);
|
||||
}
|
||||
src -= xr;
|
||||
dest += pinc;
|
||||
} while (--doo);
|
||||
src += xr;
|
||||
if (highefx & FVB_SCANLINES)
|
||||
dest += pitch * (yscale >> 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pinc = pitch - ((xr * xscale) * 3);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
int doo = yscale;
|
||||
|
||||
if (highefx & FVB_SCANLINES)
|
||||
doo -= yscale >> 1;
|
||||
do {
|
||||
for (x = xr; x; x--, src++) {
|
||||
int too = xscale;
|
||||
do {
|
||||
uint32 tmp = palettetranslate[(uint32) * src];
|
||||
*(uint8*)dest = tmp;
|
||||
*((uint8*)dest + 1) = tmp >> 8;
|
||||
*((uint8*)dest + 2) = tmp >> 16;
|
||||
dest += 3;
|
||||
|
||||
//*(uint32 *)dest=palettetranslate[*src];
|
||||
//dest+=4;
|
||||
} while (--too);
|
||||
}
|
||||
src -= xr;
|
||||
dest += pinc;
|
||||
} while (--doo);
|
||||
src += xr;
|
||||
if (highefx & FVB_SCANLINES)
|
||||
dest += pitch * (yscale >> 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pinc = pitch - ((xr * xscale) << 1);
|
||||
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
int doo = yscale;
|
||||
|
||||
if (highefx & FVB_SCANLINES)
|
||||
doo -= yscale >> 1;
|
||||
do {
|
||||
for (x = xr; x; x--, src++) {
|
||||
int too = xscale;
|
||||
do {
|
||||
*(uint16*)dest = palettetranslate[*src];
|
||||
dest += 2;
|
||||
} while (--too);
|
||||
}
|
||||
src -= xr;
|
||||
dest += pinc;
|
||||
} while (--doo);
|
||||
src += xr;
|
||||
if (highefx & FVB_SCANLINES)
|
||||
dest += pitch * (yscale >> 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else
|
||||
switch (Bpp) {
|
||||
case 4:
|
||||
pinc = pitch - (xr << 2);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
for (x = xr; x; x--) {
|
||||
*(uint32*)dest = palettetranslate[(uint32) * src];
|
||||
dest += 4;
|
||||
src++;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc = pitch - (xr + xr + xr);
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
for (x = xr; x; x--) {
|
||||
uint32 tmp = palettetranslate[(uint32) * src];
|
||||
*(uint8*)dest = tmp;
|
||||
*((uint8*)dest + 1) = tmp >> 8;
|
||||
*((uint8*)dest + 2) = tmp >> 16;
|
||||
dest += 3;
|
||||
src++;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc = pitch - (xr << 1);
|
||||
|
||||
for (y = yr; y; y--, src += 256 - xr) {
|
||||
for (x = xr >> 1; x; x--) {
|
||||
*(uint32*)dest = palettetranslate[*(uint16*)src];
|
||||
dest += 4;
|
||||
src += 2;
|
||||
}
|
||||
dest += pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (specbuf) {
|
||||
if (specbuf32bpp) {
|
||||
int mult = (silt == 3) ? 3 : 2;
|
||||
|
||||
if (silt == 3)
|
||||
hq3x_32((uint8*)specbuf, (uint8*)specbuf32bpp, xr, yr, xr * 3 * sizeof(uint32));
|
||||
else
|
||||
hq2x_32((uint8*)specbuf, (uint8*)specbuf32bpp, xr, yr, xr * 2 * sizeof(uint32));
|
||||
|
||||
if (backBpp == 2)
|
||||
Blit32to16(specbuf32bpp, (uint16*)destbackup, xr * mult, yr * mult, pitchbackup, backshiftr, backshiftl);
|
||||
else// == 3
|
||||
Blit32to24(specbuf32bpp, (uint8*)destbackup, xr * mult, yr * mult, pitchbackup);
|
||||
} else {
|
||||
if (silt == 3)
|
||||
hq3x_32((uint8*)specbuf, destbackup, xr, yr, pitchbackup);
|
||||
else
|
||||
hq2x_32((uint8*)specbuf, destbackup, xr, yr, pitchbackup);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/drivers/common/vidblit.h
Normal file
25
src/drivers/common/vidblit.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int eefx, int specfilt);
|
||||
void SetPaletteBlitToHigh(uint8 *src);
|
||||
void KillBlitToHigh(void);
|
||||
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale);
|
||||
void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale, int efx, int special);
|
||||
Reference in New Issue
Block a user