File: plugin1.c

package info (click to toggle)
855resolution 0.3-4
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 96 kB
  • ctags: 93
  • sloc: ansic: 402; makefile: 67; sh: 30
file content (146 lines) | stat: -rw-r--r-- 3,589 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* 855resolution by Alain Poirier
 *
 * Currently only tested on a Dell 510m with BIOS A04
 * *VERY* likely that this won't work yet on any
 * other versions or chipsets!!!
 *
 * This code is based on the techniques used in :
 *
 *   - 855patch.  Many thanks to Christian Zietz (czietz gmx net)
 *     for demonstrating how to shadow the VBIOS into system RAM
 *     and then modify it.
 *
 *   - 1280patch by Andrew Tipton (andrewtipton null li).
 *
 * This source code is into the public domain.
 */
#include <stdio.h>
#include <sys/io.h>

#include "../plugin.h"

struct vbios_modeline {
    unsigned long clock;

    unsigned short x1;
    unsigned short htotal;
    unsigned short x2;
    unsigned short hblank;
    unsigned short hsyncstart;
    unsigned short hsyncend;

    unsigned short y1;
    unsigned short vtotal;
    unsigned short y2;
    unsigned short vblank;
    unsigned short vsyncstart;
    unsigned short vsyncend;
} __attribute__((packed));

struct vbios_resolution {
    unsigned char unknown[6];

    struct vbios_modeline modelines[];
} __attribute__((packed));

#define TIMING_60 0
#define TIMING_75 1
#define TIMING_85 2

static int freqs[] = { 60, 75, 85 };

static void unlock_bios(void) {
    outl(0x8000005a, 0xcf8);
    outb(0x33, 0xcfe);
}

static void relock_bios(void) {
    outl(0x8000005a, 0xcf8);
    outb(0x11, 0xcfe);
}

static int detect_vbios_type(struct vbios_mode *modes) {
short int r1, r2;
float f;

    r1 = r2 = 32000;
    while(modes->mode != 0xff) {
        if(modes->resolution <= r1) {
        r1 = modes->resolution;
    } else {
        if(modes->resolution <= r2) {
            r2 = modes->resolution;
        }
    }

        modes++;
    }

    f = ((float) (r2-r1-6)) / sizeof(struct vbios_modeline);

    return f == (int) f;
}

static unsigned char *get_vbios_version(unsigned char *vbios_cfg) {
    return vbios_cfg+29;
}

static void get_resolution(struct vbios_resolution *resolution, unsigned int *x, unsigned int *y) {
struct vbios_modeline *modeline;
int i;

    *x = resolution->modelines[0].x1+1;
    *y = resolution->modelines[0].y1+1;

    for(i=0; i<3; i++)
    {
        modeline = &resolution->modelines[i];

    if(modeline->x1 == resolution->modelines[0].x1) {
            printf("  (Modeline : %ld %d %d %d %d %d %d %d %d)\n",
                modeline->clock,
                modeline->x1+1, modeline->hsyncstart, modeline->hsyncend, modeline->htotal,
                modeline->y1+1, modeline->vsyncstart, modeline->vsyncend, modeline->vtotal);
    }
    }
}

static void set_resolution(struct vbios_resolution *resolution, unsigned int x, unsigned int y) {
struct vbios_modeline *modeline;
int i;

    unlock_bios();

    for(i=0; i<3; i++) {
        modeline = &resolution->modelines[i];

        if(modeline->x1 == resolution->modelines[0].x1) {
            modeline->x1 = modeline->x2 = x-1;
            modeline->y1 = modeline->y2 = y-1;

                /* WARNING: I don't know at all what are the formulas
            to calculate these values !
            The following lines are only an example.
            */
            modeline->clock = freqs[i] * x;

            modeline->hsyncstart = x+10;
            modeline->hsyncend   = x+20;
            modeline->htotal     = x+30;

            modeline->vsyncstart = y+10;
            modeline->vsyncend   = y+20;
            modeline->vtotal     = y+30;
        }
    }

    relock_bios();
}

struct plugin plugin1 = {
    detect_vbios_type,
    get_vbios_version,
    (get_resolution_type) get_resolution,
    (set_resolution_type) set_resolution
};