Commit 8bd59272 authored by aliaspider's avatar aliaspider
Browse files

more cleanups

parent f2895ec9
.global invalidate_cache_region
.global invoke_kernel_custom_code
.global invalidate_icache_all
.global invalidate_dcache_all
.equ CACHE_SIZE, (16 * 1024)
.equ CACHE_LINE_SIZE, 32
.equ CACHE_LINES, (CACHE_SIZE / CACHE_LINE_SIZE)
.equ CACHE_WAYS, 4
#define nop16b() \
nop; \
nop; \
nop; \
nop \
#define nop64b() \
nop16b(); \
nop16b(); \
nop16b(); \
nop16b() \
#define nop256b() \
nop64b(); \
nop64b(); \
nop64b(); \
nop64b() \
#define nop1kb() \
nop256b(); \
nop256b(); \
nop256b(); \
nop256b() \
#define nop4kb() \
nop1kb(); \
nop1kb(); \
nop1kb(); \
nop1kb() \
#define nop16kb() \
nop4kb(); \
nop4kb(); \
nop4kb(); \
nop4kb() \
invalidate_cache_region:
mov r2, #0x0
swi 0x9f0002
bx lr
invoke_kernel_custom_code:
swi 0x90007a
bx lr
invalidate_dcache_all:
ldr r0, dcache_buffer
mov r1, #(CACHE_SIZE / 2)
1:
ldr r2, [r0], #4
subs r1, r1, #1
bne 1b
bx lr
dcache_buffer:
.word _dcache_buffer
.balign 16384
invalidate_icache_all:
nop16kb()
bx lr
.section bss
.balign 32768
.comm _dcache_buffer (CACHE_SIZE * 2)
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
#include "frame_skip.h"
#include "memmap.h"
#ifndef uclock_t
#define uclock_t unsigned int
#endif
#define TICKS_PER_SEC 1000000UL
//#define CPU_FPS 60
static int CPU_FPS=60;
static uclock_t F;
#define MAX_FRAMESKIP 10
static char init_frame_skip = 1;
char skip_next_frame = 0;
static struct timeval init_tv = { 0, 0 };
void reset_frame_skip(void)
{
//static Uint8 init=0;
init_tv.tv_usec = 0;
init_tv.tv_sec = 0;
skip_next_frame = 0;
init_frame_skip = 1;
CPU_FPS=Memory.ROMFramesPerSecond;
F = (uclock_t) ((double) TICKS_PER_SEC / CPU_FPS);
}
uclock_t get_ticks(void)
{
struct timeval tv;
gettimeofday(&tv, 0);
if (init_tv.tv_sec == 0)
init_tv = tv;
return (tv.tv_sec - init_tv.tv_sec) * TICKS_PER_SEC + tv.tv_usec -
init_tv.tv_usec;
}
int frame_skip(void)
{
static int f2skip;
static uclock_t sec = 0;
static uclock_t rfd;
static uclock_t target;
static int nbFrame = 0;
static int skpFrm = 0;
if (init_frame_skip) {
init_frame_skip = 0;
target = get_ticks();
nbFrame = 0;
//f2skip=0;
//skpFrm=0;
sec = 0;
return 0;
}
target += F;
if (f2skip > 0) {
f2skip--;
skpFrm++;
return 1;
} else
skpFrm = 0;
rfd = get_ticks();
if (rfd < target && f2skip == 0) {
while (get_ticks() < target);
} else {
f2skip = (rfd - target) / (double) F;
if (f2skip > MAX_FRAMESKIP) {
f2skip = MAX_FRAMESKIP;
reset_frame_skip();
}
// printf("Skip %d frame(s) %lu %lu\n",f2skip,target,rfd);
}
nbFrame++;
if (get_ticks() - sec >= TICKS_PER_SEC) {
nbFrame = 0;
sec = get_ticks();
}
return 0;
}
#ifndef _FRAME_SKIP_H
#define _FRAME_SKIP_H
void reset_frame_skip(void);
int frame_skip(void);
#endif
unsigned char gammatab[10][32]={
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F},
{0x00,0x01,0x02,0x03,0x04,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
0x11,0x12,0x13,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F},
{0x00,0x01,0x03,0x04,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,
0x12,0x13,0x14,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F},
{0x00,0x02,0x04,0x06,0x07,0x08,0x09,0x0A,0x0C,0x0D,0x0E,0x0F,0x0F,0x10,0x11,0x12,
0x13,0x14,0x15,0x16,0x16,0x17,0x18,0x19,0x19,0x1A,0x1B,0x1C,0x1C,0x1D,0x1E,0x1F},
{0x00,0x03,0x05,0x07,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,
0x14,0x15,0x16,0x17,0x17,0x18,0x19,0x19,0x1A,0x1B,0x1B,0x1C,0x1D,0x1D,0x1E,0x1F},
{0x00,0x05,0x07,0x09,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x14,0x15,
0x16,0x16,0x17,0x18,0x18,0x19,0x1A,0x1A,0x1B,0x1B,0x1C,0x1C,0x1D,0x1D,0x1E,0x1F},
{0x00,0x07,0x0A,0x0C,0x0D,0x0E,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x15,0x16,0x17,
0x17,0x18,0x18,0x19,0x1A,0x1A,0x1B,0x1B,0x1B,0x1C,0x1C,0x1D,0x1D,0x1E,0x1E,0x1F},
{0x00,0x0B,0x0D,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x16,0x17,0x17,0x18,0x18,
0x19,0x19,0x1A,0x1A,0x1B,0x1B,0x1B,0x1C,0x1C,0x1D,0x1D,0x1D,0x1E,0x1E,0x1E,0x1F},
{0x00,0x0F,0x11,0x13,0x14,0x15,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1A,0x1A,0x1A,
0x1B,0x1B,0x1B,0x1C,0x1C,0x1C,0x1C,0x1D,0x1D,0x1D,0x1D,0x1E,0x1E,0x1E,0x1E,0x1F},
{0x00,0x15,0x17,0x18,0x19,0x19,0x1A,0x1A,0x1B,0x1B,0x1B,0x1B,0x1C,0x1C,0x1C,0x1C,
0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1F}
};
This diff is collapsed.
This diff is collapsed.
/*
Simple PNG handling library
Under GPL v2 License
2011 by bitrider
*/
#include <stdlib.h>
#include "lodepng.h"
#include "png.h"
#define ERROR(err) {if (error) (*error) = PNG_ERROR_OPENING; return NULL;}
gBITMAP *load_png(char *filename, int *error) /* We need to open the file */
{
gBITMAP *img = NULL;
unsigned int e;
// allocate memory
img = malloc(sizeof(gBITMAP));
if (!img) ERROR(PNG_ERROR_MEMORY);
img->data = NULL;
e = LodePNG_decode32_file(&img->data, &img->w, &img->h, filename);
if (e) {
gDestroyBitmap(img);
ERROR(e);
}
img->bpp = 32;
if (error) (*error) = PNG_OK;
return img;
}
int save_png(gBITMAP *img, char *filename) {
if ((!img) || (!img->data) || (img->bpp != 32)) return PNG_ERROR_INVALID_INPUT;
return LodePNG_encode32_file(filename, img->data, img->w, img->h);
}
#ifndef __PNG_H__
#define __PNG_H__
#include "graphics.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PNG_OK 0
#define PNG_ERROR_OPENING 1
#define PNG_ERROR_READING 2
#define PNG_ERROR_NOT_PNG 3
#define PNG_ERROR_PNG_STRUCTS 4
#define PNG_ERROR_MEMORY 5
#define PNG_ERROR 6
#define PNG_ERROR_INVALID_INPUT 7
gBITMAP *load_png(char *filename, int *error);
int save_png(gBITMAP *img, char *filename);
#ifdef __cplusplus
}
#endif
#endif
/*
* quick tool to set various timings for Wiz
*
* Copyright (c) Gražvydas "notaz" Ignotas, 2009
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the organization nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* HTOTAL: X VTOTAL: 341
* HSWIDTH: 1 VSWIDTH: 0
* HASTART: 37 VASTART: 17
* HAEND: 277 VAEND: 337
*
* 120Hz
* pcd 8, 447: + 594us
* pcd 9, 397: + 36us
* pcd 10, 357: - 523us
* pcd 11, 325: +1153us
*
* 'lcd_timings=397,1,37,277,341,0,17,337;dpc_clkdiv0=9'
* 'ram_timings=2,9,4,1,1,1,1'
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pollux_set.h"
/* parse stuff */
static int parse_lcd_timings(const char *str, void *data)
{
int *lcd_timings = (int *)data;
const char *p = str;
int ret, c;
ret = sscanf(str, "%d,%d,%d,%d,%d,%d,%d,%d",
&lcd_timings[0], &lcd_timings[1], &lcd_timings[2], &lcd_timings[3],
&lcd_timings[4], &lcd_timings[5], &lcd_timings[6], &lcd_timings[7]);
if (ret != 8)
return -1;
/* skip seven commas */
for (c = 0; c < 7 && *p != 0; p++)
if (*p == ',')
c++;
if (c != 7)
return -1;
/* skip last number */
while ('0' <= *p && *p <= '9')
p++;
return p - str;
}
static int parse_ram_timings(const char *str, void *data)
{
int *ram_timings = (int *)data;
const char *p = str;
int ret, c;
float cas;
ret = sscanf(p, "%f,%d,%d,%d,%d,%d,%d",
&cas, &ram_timings[1], &ram_timings[2], &ram_timings[3],
&ram_timings[4], &ram_timings[5], &ram_timings[6]);
if (ret != 7)
return -1;
if (cas == 2)
ram_timings[0] = 1;
else if (cas == 2.5)
ram_timings[0] = 2;
else if (cas == 3)
ram_timings[0] = 3;
else
return -1;
for (c = 0; c < 6 && *p != 0; p++)
if (*p == ',')
c++;
if (c != 6)
return -1;
while ('0' <= *p && *p <= '9')
p++;
return p - str;
}
static int parse_decimal(const char *str, void *data)
{
char *ep;
*(int *)data = strtoul(str, &ep, 10);
if (ep == str)
return -1;
return ep - str;
}
/* validate and apply stuff */
static int apply_lcd_timings(volatile unsigned short *memregs, void *data)
{
int *lcd_timings = (int *)data;
int i;
for (i = 0; i < 8; i++) {
if (lcd_timings[i] & ~0xffff) {
fprintf(stderr, "pollux_set: invalid lcd timing %d: %d\n", i, lcd_timings[i]);
return -1;
}
}
for (i = 0; i < 8; i++)
memregs[(0x307c>>1) + i] = lcd_timings[i];
return 0;
}
static const struct {
signed char adj; /* how to adjust value passed by user */
signed short min; /* range of */
signed short max; /* allowed values (inclusive) */
}
ram_ranges[] = {
{ 0, 1, 3 }, /* cas (cl) */
{ -2, 0, 15 }, /* trc */
{ -2, 0, 15 }, /* tras */
{ 0, 0, 15 }, /* twr */
{ 0, 0, 15 }, /* tmrd */
{ 0, 0, 15 }, /* trp */
{ 0, 0, 15 }, /* trcd */
};
static int apply_ram_timings(volatile unsigned short *memregs, void *data)
{
int *ram_timings = (int *)data;
int i, val;
for (i = 0; i < 7; i++)
{
ram_timings[i] += ram_ranges[i].adj;
if (ram_timings[i] < ram_ranges[i].min || ram_timings[i] > ram_ranges[i].max) {
fprintf(stderr, "pollux_set: invalid RAM timing %d\n", i);
return -1;
}
}
val = memregs[0x14802>>1] & 0x0f00;
val |= (ram_timings[4] << 12) | (ram_timings[5] << 4) | ram_timings[6];
memregs[0x14802>>1] = val;
val = memregs[0x14804>>1] & 0x4000;
val |= (ram_timings[0] << 12) | (ram_timings[1] << 8) |
(ram_timings[2] << 4) | ram_timings[3];
val |= 0x8000;
memregs[0x14804>>1] = val;
for (i = 0; i < 0x100000 && (memregs[0x14804>>1] & 0x8000); i++)
;
return 0;
}
static int apply_dpc_clkdiv0(volatile unsigned short *memregs, void *data)
{
int pcd = *(int *)data;
int tmp;
if ((pcd - 1) & ~0x3f) {
fprintf(stderr, "pollux_set: invalid lcd clkdiv0: %d\n", pcd);
return -1;
}
pcd = (pcd - 1) & 0x3f;
tmp = memregs[0x31c4>>1];
memregs[0x31c4>>1] = (tmp & ~0x3f0) | (pcd << 4);
return 0;
}
static int apply_cpuclk(volatile unsigned short *memregs, void *data)
{
volatile unsigned int *memregl = (volatile unsigned int *)memregs;
int mhz = *(int *)data;
int mdiv, pdiv, sdiv = 0;
int i, v;
// m = MDIV, p = PDIV, s = SDIV
#define SYS_CLK_FREQ 27
pdiv = 9;
mdiv = (mhz * pdiv) / SYS_CLK_FREQ;
if (mdiv & ~0x3ff)
return -1;
v = (pdiv<<18) | (mdiv<<8) | sdiv;
memregl[0xf004>>2] = v;
memregl[0xf07c>>2] |= 0x8000;
for (i = 0; (memregl[0xf07c>>2] & 0x8000) && i < 0x100000; i++)
;
return 0;
}
static int lcd_timings[8];
static int ram_timings[7];
static int dpc_clkdiv0;
static int cpuclk;
static const char lcd_t_help[] = "htotal,hswidth,hastart,haend,vtotal,vswidth,vastart,vaend";
static const char ram_t_help[] = "CAS,tRC,tRAS,tWR,tMRD,tRP,tRCD";
static const struct {
const char *name;
const char *help;
int (*parse)(const char *str, void *data);
int (*apply)(volatile unsigned short *memregs, void *data);
void *data;
}
all_params[] = {
{ "lcd_timings", lcd_t_help, parse_lcd_timings, apply_lcd_timings, lcd_timings },
{ "ram_timings", ram_t_help, parse_ram_timings, apply_ram_timings, ram_timings },
{ "dpc_clkdiv0", "divider", parse_decimal, apply_dpc_clkdiv0, &dpc_clkdiv0 },
{ "clkdiv0", "divider", parse_decimal, apply_dpc_clkdiv0, &dpc_clkdiv0 }, /* alias */
{ "cpuclk", "MHZ", parse_decimal, apply_cpuclk, &cpuclk },
};
#define ALL_PARAM_COUNT (sizeof(all_params) / sizeof(all_params[0]))
/*
* set timings based on preformated string (see usage() below for params).
* returns 0 on success.
*/
int pollux_set(volatile unsigned short *memregs, const char *str)
{
int parsed_params[ALL_PARAM_COUNT];
int applied_params[ALL_PARAM_COUNT];
int applied_something = 0;
const char *p, *po;
int i, ret;
if (str == NULL)
return -1;
memset(parsed_params, 0, sizeof(parsed_params));
memset(applied_params, 0, sizeof(applied_params));
p = str;
while (1)
{
again:
while (*p == ';' || *p == ' ')
p++;
if (*p == 0)
break;
for (i = 0; i < ALL_PARAM_COUNT; i++)
{
int param_len = strlen(all_params[i].name);
if (strncmp(p, all_params[i].name, param_len) == 0 && p[param_len] == '=')
{
p += param_len + 1;
ret = all_params[i].parse(p, all_params[i].data);
if (ret < 0) {
fprintf(stderr, "pollux_set parser: error at %-10s\n", p);
fprintf(stderr, " valid format is: <%s>\n", all_params[i].help);
return -1;
}
parsed_params[i] = 1;
p += ret;
goto again;
}
}
/* Unknown param. Attempt to be forward compatible and ignore it. */
for (po = p; *p != 0 && *p != ';'; p++)
;
fprintf(stderr, "unhandled param: ");
fwrite(po, 1, p - po, stderr);
fprintf(stderr, "\n");
}
/* validate and apply */
for (i = 0; i < ALL_PARAM_COUNT; i++)
{
if (!parsed_params[i])
continue;
ret = all_params[i].apply(memregs, all_params[i].data);
if (ret < 0) {
fprintf(stderr, "pollux_set: failed to apply %s (bad value?)\n",
all_params[i].name);
continue;
}
applied_something = 1;
applied_params[i] = 1;
}
if (applied_something)
{
int c;
printf("applied: ");
for (i = c = 0; i < ALL_PARAM_COUNT; i++)
{
if (!applied_params[i])
continue;
if (c != 0)
printf(", ");
printf("%s", all_params[i].name);
c++;
}
printf("\n");