OSDN Git Service

68e33118714721c5cc18cfb74007c983729d6a26
[motonesemu/motonesemu.git] / emulator / ppucore / vscreen.c
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "libio.h"
5 #include "tools.h"
6 #include "vga.h"
7 #include "ppucore.h"
8 #include "vram.h"
9 #include "sprite.h"
10
11 void load_attribute(unsigned char bank, int tile_index, struct palette *plt);
12 void load_pattern(unsigned char bank, unsigned char ptn_index, struct tile_2* pattern);
13 void load_spr_attribute(struct sprite_attr sa, struct palette *plt);
14
15 struct tile_rgb15_line {
16     struct rgb15 d[8];
17 };
18
19 struct tile_rgb15 {
20     struct tile_rgb15_line l[8];
21 };
22
23 static struct tile_rgb15 *vscreen;
24
25 static unsigned char bg_pattern_bank;
26 static unsigned char spr_pattern_bank;
27 static unsigned short   name_tbl_base;
28
29 void vscreenn_dot_get(int x, int y, struct rgb15 *col) {
30     int tile_id, tile_id_x, tile_id_y;
31     int inner_x, inner_y;
32     struct tile_rgb15* tile;
33
34     tile_id_x = x / TILE_DOT_SIZE;
35     tile_id_y = y / TILE_DOT_SIZE;
36     tile_id = tile_id_x + tile_id_y * H_SCREEN_TILE_SIZE;
37     tile = vscreen + tile_id;
38
39     inner_x = x % TILE_DOT_SIZE;
40     inner_y = y % TILE_DOT_SIZE;
41     *col = tile->l[inner_y].d[inner_x];
42 }
43
44 void vscreenn_dot_set(int x, int y, struct rgb15 *col) {
45     int tile_id, tile_id_x, tile_id_y;
46     int inner_x, inner_y;
47     struct tile_rgb15* tile;
48
49     tile_id_x = x / TILE_DOT_SIZE;
50     tile_id_y = y / TILE_DOT_SIZE;
51     tile_id = tile_id_x + tile_id_y * H_SCREEN_TILE_SIZE;
52     tile = vscreen + tile_id;
53
54     inner_x = x % TILE_DOT_SIZE;
55     inner_y = y % TILE_DOT_SIZE;
56     tile->l[inner_y].d[inner_x] = *col;
57 }
58
59 static int pal_index(struct tile_2 *ptn, int l, int dot_x) {
60     switch (dot_x) {
61         case 0:
62             return ptn->b0.l[l].dot0 * 2 + ptn->b1.l[l].dot0;
63         case 1:
64             return ptn->b0.l[l].dot1 * 2 + ptn->b1.l[l].dot1;
65         case 2:
66             return ptn->b0.l[l].dot2 * 2 + ptn->b1.l[l].dot2;
67         case 3:
68             return ptn->b0.l[l].dot3 * 2 + ptn->b1.l[l].dot3;
69         case 4:
70             return ptn->b0.l[l].dot4 * 2 + ptn->b1.l[l].dot4;
71         case 5:
72             return ptn->b0.l[l].dot5 * 2 + ptn->b1.l[l].dot5;
73         case 6:
74             return ptn->b0.l[l].dot6 * 2 + ptn->b1.l[l].dot6;
75         case 7:
76         default:
77             return ptn->b0.l[l].dot7 * 2 + ptn->b1.l[l].dot7;
78     }
79 }
80
81 void set_bgtile(int tile_id) {
82     struct palette plt;
83     struct tile_2 ptn;
84     unsigned char name_index;
85     struct tile_rgb15* set_data;
86     int i,j;
87
88     load_attribute(0, tile_id, &plt);
89
90     name_index = vram_data_get(name_tbl_base + tile_id);
91     load_pattern(bg_pattern_bank, name_index, &ptn);
92
93     set_data = vscreen + tile_id;
94     for (i = 0; i < TILE_DOT_SIZE; i++) {
95         //display shows left to right with high bit to low bit
96         for (j = 0; j < 8; j++) {
97             int pi = pal_index(&ptn, i, j);
98             if (pi) {
99                 //dprint("%d, %d, colind:%d\n", j, i, pi);
100                 set_data->l[i].d[7 - j] = plt.col[pi];
101             }
102         }
103     }
104
105 }
106
107 void set_sprite(int x, int y, int tile_id, struct sprite_attr sa) {
108     struct palette plt;
109     struct tile_2 ptn;
110     int i, j;
111
112     load_spr_attribute(sa, &plt);
113
114     load_pattern(spr_pattern_bank, tile_id, &ptn);
115
116     //display shows left to right with high bit to low bit
117     for (i = 0; i < TILE_DOT_SIZE; i++) {
118         if (sa.flip_h) {
119             if (sa.flip_v) {
120                 for (j = 0; j < 8; j++) {
121                     int pi = pal_index(&ptn, i, j);
122                     if (pi)
123                         vscreenn_dot_set(x + j, y + 7 - i, &plt.col[pi]);
124                 }
125             }
126             else {
127                 for (j = 0; j < 8; j++) {
128                     int pi = pal_index(&ptn, i, j);
129                     if (pi)
130                         vscreenn_dot_set(x + j, y + i, &plt.col[pi]);
131                 }
132             }
133         }
134         else {
135             if (sa.flip_v) {
136                 for (j = 0; j < 8; j++) {
137                     int pi = pal_index(&ptn, i, j);
138                     if (pi)
139                         vscreenn_dot_set(x + 7 - j, y + 7 - i, &plt.col[pi]);
140                 }
141             }
142             else {
143                 for (j = 0; j < 8; j++) {
144                     int pi = pal_index(&ptn, i, j);
145                     if (pi)
146                         vscreenn_dot_set(x + 7 - j, y + i, &plt.col[pi]);
147                 }
148             }
149         }
150     }
151 }
152
153 void set_bg_pattern_bank(unsigned char bank) {
154     bg_pattern_bank = bank;
155 }
156 void set_spr_pattern_bank(unsigned char bank) {
157     spr_pattern_bank = bank;
158 }
159 void set_name_tbl_base(unsigned char sw) {
160     switch (sw) {
161         case 0:
162             name_tbl_base = NAME0_START;
163             break;
164         case 1:
165             name_tbl_base = NAME1_START;
166             break;
167         case 2:
168             name_tbl_base = NAME2_START;
169             break;
170         case 3:
171         default:
172             name_tbl_base = NAME3_START;
173             break;
174     }
175 }
176
177 int vscreen_init(void) {
178     bg_pattern_bank = 0;
179     spr_pattern_bank = 0;
180     name_tbl_base = NAME0_START;
181
182     vscreen = (struct tile_rgb15 *) malloc(
183         sizeof (struct tile_rgb15) * VIRT_SCREEN_TILE_SIZE * VIRT_SCREEN_TILE_SIZE);
184     if (vscreen == NULL)
185         return FALSE;
186     memset(vscreen, 0, sizeof (struct tile_rgb15) * VIRT_SCREEN_TILE_SIZE * VIRT_SCREEN_TILE_SIZE);
187
188     //dprint("tile_1_line:%d tile_2 size:%d\n", sizeof(struct tile_1_line), sizeof(struct tile_2));
189
190     return TRUE;
191 }
192
193 void clean_vscreen(void) {
194     free(vscreen);
195 }
196