for (scanline = 0; scanline < SCAN_LINE; scanline++) {
if (ctrl_reg2.show_sprite) {
//sprite in the back
- load_sprite(FALSE, scanline);
+ load_sprite_old(FALSE, scanline);
}
if (ctrl_reg2.show_bg/**/) {
//back ground image is pre-loaded. load 1 line ahead of drawline.
if (scanline == 0)
- load_background(scanline);
+ load_background_old(scanline);
if (scanline < SCAN_LINE - 1)
load_background(scanline + 8);
}
if (ctrl_reg2.show_sprite) {
//foreground sprite
- load_sprite(TRUE, scanline);
+ load_sprite_old(TRUE, scanline);
}
vga_xfer(scanline);
}
if (ctrl_reg2.show_sprite) {
//sprite in the back
- load_sprite(FALSE, scanline);
+ load_sprite_old(FALSE, scanline);
}
if (ctrl_reg2.show_bg/**/) {
//back ground image is pre-loaded. load 1 line ahead of drawline.
if (scanline == 0)
- load_background(scanline);
+ load_background_old(scanline);
if (scanline < SCAN_LINE - 1)
- load_background(scanline + 8);
+ load_background_old(scanline + 8);
}
if (ctrl_reg2.show_sprite) {
//foreground sprite
- load_sprite(TRUE, scanline);
+ load_sprite_old(TRUE, scanline);
}
- vga_xfer(scanline);
+ vga_xfer_old(scanline);
}
}
else {
#include "ppucore.h"
void vscreenn_dot_get(int x, int y, struct rgb15 *col);
+struct rgb15 *get_vscreen_head(void);
#define VSCREEN_WIDTH (H_SCREEN_TILE_SIZE * TILE_DOT_SIZE)
#define VSCREEN_HEIGHT (V_SCREEN_TILE_SIZE * TILE_DOT_SIZE)
static int vscrn_y, vscrn_y_old;
static struct rgb15 *vga_col;
-void vga_xfer(int scanline) {
+void vga_xfer_old(int scanline) {
int vscrn_x, vscrn_x_old;
int vga_x;
struct rgb15 *col_old;
}
}
+static struct rgb15 *vs_col, *vs_head;
+static struct rgb15 *vga_col;
+
+void vga_posinit(void) {
+ vs_head = (struct rgb15 *)get_vscreen_head();
+}
+
+void vga_xfer(int vs_x, int vs_y) {
+ int vga_x, vga_y, vga_x_next;
+ struct rgb15 *vga_col_next;
+
+ //dprint("vga_xfer x:%d, y:%d\n", vs_x, vs_y);
+ //x direction scale is 640/256.
+ //y direction scale is 480/240
+
+ if (vs_x == 0) {
+ int tile_id, tile_id_y;
+ int inner_y;
+
+ tile_id_y = vs_y / TILE_DOT_SIZE;
+ tile_id = tile_id_y * H_SCREEN_TILE_SIZE;
+ inner_y = vs_y % TILE_DOT_SIZE;
+
+ vs_col = vs_head + tile_id * TILE_DOT_SIZE * TILE_DOT_SIZE + inner_y * TILE_DOT_SIZE;
+
+ vga_y = vs_y * VGA_HEIGHT / VSCREEN_HEIGHT;
+ vga_col = vga_base + vga_y * VGA_WIDTH;
+ }
+ else {
+ if (vs_x % TILE_DOT_SIZE) {
+ vs_col++;
+ }
+ else {
+ vs_col += (TILE_DOT_SIZE - 1) * TILE_DOT_SIZE + 1;
+ }
+ }
+
+ vga_x = vs_x * VGA_WIDTH / VSCREEN_WIDTH;
+ vga_x_next = (vs_x + 1) * VGA_WIDTH / VSCREEN_WIDTH;
+ vga_col_next = vga_col + vga_x_next - vga_x;
+
+ //copy color in vscreen to vga buffer.
+ while ( vga_col != vga_col_next) {
+ *vga_col = *vs_col;
+ //double the copy of the next dot below as well
+ //since y direction scale is just x2.
+ *(vga_col + VGA_WIDTH) = *vs_col;
+ vga_col++;
+ }
+
+}
+
int vga_xfer_init(void) {
emp_red = FALSE;
emp_green = FALSE;
struct tile_rgb15_line l[8];
};
+struct sprite_buf_reg {
+ struct palette plt;
+ struct tile_2 ptn;
+};
+
static struct tile_rgb15 *vscreen;
static unsigned char bg_pattern_bank;
static unsigned short bg_name_tbl_base;
static unsigned char bg_attr_tbl_bank;
+
+#define SPRITE_PREFETCH_CNT 64
+static struct ppu_sprite_reg sprite_temp_buf [SPRITE_PREFETCH_CNT];
+static struct sprite_buf_reg sprite_buf [SPRITE_PREFETCH_CNT];
+static int sprite_hit_cnt;
+
+
void vscreenn_dot_get(int x, int y, struct rgb15 *col) {
int tile_id, tile_id_x, tile_id_y;
int inner_x, inner_y;
}
-int load_background(int scanline) {
+int load_background_old(int scanline) {
int i, start, end;
//load tile must be executed every 8 scanlines only.
return TRUE;
}
+static struct palette plt;
+static struct tile_2 ptn;
+static struct tile_rgb15* set_data;
+int load_background(int x, int y) {
+ //dprint("load bg x:%d, y:%d...\n", x, y);
+
+ int inner_x, inner_y;
+
+
+ //tile loading happens every 8 dots only.
+ if (x % TILE_DOT_SIZE == 0) {
+ int tile_id, tile_id_x, tile_id_y;
+ unsigned char name_index;
+
+ tile_id_x = x / TILE_DOT_SIZE;
+ tile_id_y = y / TILE_DOT_SIZE;
+ tile_id = tile_id_x + tile_id_y * H_SCREEN_TILE_SIZE;
+
+ //dprint("load tile.\n");
+ load_attribute(bg_attr_tbl_bank, tile_id, &plt);
+ name_index = vram_data_get(bg_name_tbl_base + tile_id);
+ load_pattern(bg_pattern_bank, name_index, &ptn);
+ set_data = vscreen + tile_id;
+ }
+
+
+ inner_x = x % TILE_DOT_SIZE;
+ inner_y = y % TILE_DOT_SIZE;
+
+ int pi = pal_index(&ptn, inner_y, inner_x);
+ if (pi) {
+ //dprint("%d, %d, colind:%d\n", j, i, pi);
+ set_data->l[inner_y].d[7 - inner_x] = plt.col[pi];
+ }
+ else {
+ //transparent bg color is read from sprite 0x10 color.
+ pi = vram_data_get(TRANSPARENT_PALETTE_ADDR);
+ palette_index_to_rgb15(pi, &set_data->l[inner_y].d[7 - inner_x]);
+ }
+
+ return TRUE;
+}
+
void set_sprite(int x, int y, int tile_id, struct sprite_attr sa) {
struct palette plt;
}
}
-int load_sprite(int foreground, int scanline) {
+int load_sprite_old(int foreground, int scanline) {
int i;
struct sprite_attr sa;
unsigned char x, y, tile, tmp;
return TRUE;
}
+//prefetch sprite step 1.
+//load sprite temp buffer.
+int sprite_prefetch1(int srch_line) {
+ int i;
+ unsigned char tmp;
+
+ sprite_hit_cnt = 0;
+ for (i = 0; i < SPRITE_CNT; i++) {
+ int spr_y;
+ spr_y = spr_ram_tbl_get(4 * i);
+ if (srch_line < spr_y || srch_line > spr_y + TILE_DOT_SIZE)
+ continue;
+
+ if (sprite_hit_cnt < SPRITE_PREFETCH_CNT) {
+ sprite_temp_buf[sprite_hit_cnt].y = spr_y;
+ sprite_temp_buf[sprite_hit_cnt].index = spr_ram_tbl_get(4 * i + 1);
+ tmp = spr_ram_tbl_get(4 * i + 2);
+ memcpy(&sprite_temp_buf[sprite_hit_cnt].sa, &tmp, sizeof(struct sprite_attr));
+ sprite_temp_buf[sprite_hit_cnt].x = spr_ram_tbl_get(4 * i + 3);
+ }
+/*
+ dprint("sprite prefetch hit. #%d, index:%d, srch y:%d, spr y:%d, spr x:%d\n",
+ i, sprite_temp_buf[sprite_hit_cnt].index, srch_line, spr_y,
+ sprite_temp_buf[sprite_hit_cnt].x);
+*/
+ sprite_hit_cnt++;
+ }
+ return sprite_hit_cnt;
+}
+
+//prefetch sprite step 2.
+//load sprite pattern and palette.
+int sprite_prefetch2(int srch_line) {
+ int i;
+ int spr_buf_bottom;
+
+ spr_buf_bottom = sprite_hit_cnt > SPRITE_PREFETCH_CNT ? SPRITE_PREFETCH_CNT : sprite_hit_cnt;
+ for (i = 0; i < spr_buf_bottom; i++) {
+ load_spr_attribute(sprite_temp_buf[i].sa, &sprite_buf[i].plt);
+ load_pattern(spr_pattern_bank, sprite_temp_buf[i].index, &sprite_buf[i].ptn);
+ }
+ return 0;
+}
+
+int load_sprite(int foreground, int x, int y) {
+ int i;
+ int spr_buf_bottom;
+ int pi;
+
+ //sprite priority:
+ //draw lowest priority first,
+ //high priority late. highest priority comes top.
+ //seek for the topmost sprite on this spot (x, y)
+ spr_buf_bottom = sprite_hit_cnt > SPRITE_PREFETCH_CNT ? SPRITE_PREFETCH_CNT : sprite_hit_cnt;
+ for (i = 0; i < spr_buf_bottom; i++) {
+ if (sprite_temp_buf[i].x <= x && x < sprite_temp_buf[i].x + TILE_DOT_SIZE) {
+ int x_in, y_in;
+ int draw_x_in, draw_y_in;
+
+ if (sprite_temp_buf[i].sa.priority != foreground)
+ continue;
+
+ x_in = x % TILE_DOT_SIZE;
+ y_in = y % TILE_DOT_SIZE;
+ if (sprite_temp_buf[i].sa.flip_h) {
+ draw_x_in = x_in;
+ if (sprite_temp_buf[i].sa.flip_v) {
+ draw_y_in = 7 - y_in;
+ }
+ else {
+ draw_y_in = y_in;
+ }
+ }
+ else {
+ draw_x_in = 7 - x_in;
+ if (sprite_temp_buf[i].sa.flip_v) {
+ draw_y_in = 7 - y_in;
+ }
+ else {
+ draw_y_in = y_in;
+ }
+ }
+
+ pi = pal_index(&sprite_buf[i].ptn, draw_y_in, draw_x_in);
+ if (pi) {
+ //dprint("spr#%d, dot set x:%d, y:%d\n", sprite_temp_buf[i].index, x, y);
+ vscreenn_dot_set(x, y, &sprite_buf[i].plt.col[pi]);
+ if (sprite_temp_buf[i].index == 0) {
+ sprite0_hit_set();
+ }
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
void set_bg_pattern_bank(unsigned char bank) {
bg_pattern_bank = bank;
bg_attr_tbl_bank = sw;
}
+struct rgb15 *get_vscreen_head(void) {
+ return (struct rgb15 *)vscreen;
+}
+
int vscreen_init(void) {
bg_pattern_bank = 0;
spr_pattern_bank = 0;
bg_name_tbl_base = NAME0_START;
bg_attr_tbl_bank = 0;
+ sprite_hit_cnt = 0;
+
vscreen = (struct tile_rgb15 *) malloc(
sizeof (struct tile_rgb15) * VIRT_SCREEN_TILE_SIZE * VIRT_SCREEN_TILE_SIZE);
if (vscreen == NULL)