Skip to content

Commit

Permalink
[C decompilation] [th01/reiiden] Randomly shaped VRAM copy functions, #1
Browse files Browse the repository at this point in the history


So apparently, TH01 isn't double-buffered in the usual sense, and instead uses
the second hardware framebuffer (page 1) exclusively to keep the background
image and any non-animated sprites, including the cards. Then, in order to
limit flickering when animating the bullet, character and boss sprites on top
of that (or just to the limit number of VRAM accesses, who knows), ZUN goes to
great lengths and tries to make sure to only copy back the pixels that were
modified on plane 0 in the last frame.

(Which doesn't work that well though. When you play the game, you still notice
tons of flickering whenever sprites overlap.)

And by "great lengths", I mean "having a separate counterpart function for
each shape and sprite animated which recalculates and copies back the same
pixels from plane 1 to plane 0", because that's what the new functions here
lead me to believe. Both of them are only called at one place: the wave
function on the second half of Elis' entrance animation, and the horizontal
masked line function for Reimu's X attack animations.
  • Loading branch information
nmlgc committed Mar 10, 2015
1 parent 519e24c commit 6d2fa9f
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 606 deletions.
2 changes: 1 addition & 1 deletion Makefile.mak
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ bin\th01\op.exe: bin\th01\op.obj th01\op_10.c th01\op_11.c th01\op_12.cpp
$**
|

bin\th01\reiiden.exe: bin\th01\reiiden.obj th01\main_12.c th01\main_16.c
bin\th01\reiiden.exe: bin\th01\reiiden.obj th01\main_12.c th01\main_13.c th01\main_16.c
$(CC) $(CFLAGS) -ml -3 -nbin\th01\ -eREIIDEN.EXE @&&|
$**
|
Expand Down
8 changes: 8 additions & 0 deletions ReC98.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ typedef enum {
PL_B, PL_R, PL_G, PL_E, PL_COUNT
} vram_plane_t;

typedef struct {
char B, R, G, E;
} vram_planar_8_pixels_t;

typedef struct {
int B, R, G, E;
} vram_planar_16_pixels_t;

// Since array subscripts create slightly different assembly in places, we
// offer both variants.
extern char *VRAM_PLANE[PL_COUNT];
Expand Down
4 changes: 0 additions & 4 deletions th01/grps2xsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ void scale_2x(unsigned long *dst32, int src16)
mask = 0xFF00FF00; *dst32 |= _lrotr(dst_local & mask, 8);
}

typedef struct {
int B, R, G, E;
} vram_planar_16_pixels_t;

void graph_slow_2xscale_rect_1_to_0(int x0, int y0, int x1, int y1, int w1, int h1)
{
int row_p1 = (x1 / 8) + (y1 * ROW_SIZE);
Expand Down
47 changes: 47 additions & 0 deletions th01/main_13.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* ReC98
* -----
* Code segment #13 of TH01's REIIDEN.EXE
*/

#include "th01/th01.h"

#pragma option -2
#pragma option -O-
#pragma option -Z-

#include "th01/grps2xsc.c"

void egc_copy_wave_1_to_0(int x, int y, int len, int amp, int ph, int w, int h)
{
int row;
int t = ph;
for(row = 0; row < h; row++) {
int x_wave = (((long)amp * Sin8(t)) / 256) + x;
t += 256 / len;
egc_copy_rect_1_to_0(x_wave, y + row, w, 1);
}
}

void graph_copy_hline_mask_1_to_0(int x, int y, char *mask, int w)
{
vram_planar_8_pixels_t px8;
int col;
register int p = VRAM_OFFSET(x, y);
for(col = 0; col < w; col++, p++) {
if(mask[col]) {
graph_accesspage(1);
px8.B = mask[col] & VRAM_PLANE_B[p];
px8.R = mask[col] & VRAM_PLANE_R[p];
px8.G = mask[col] & VRAM_PLANE_G[p];
px8.E = mask[col] & VRAM_PLANE_E[p];
graph_accesspage(0);
grcg_setcolor_rmw(0);
VRAM_PLANE_B[p] = mask[col];
grcg_off();
VRAM_PLANE_B[p] |= px8.B;
VRAM_PLANE_R[p] |= px8.R;
VRAM_PLANE_G[p] |= px8.G;
VRAM_PLANE_E[p] |= px8.E;
}
}
}
2 changes: 2 additions & 0 deletions th01/th01.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "ReC98.h"

// Hardware
void egc_copy_rect_1_to_0(int x, int y, int w, int h);

void graph_accesspage_func(int page);
void grcg_setcolor_rmw(int color);
void grcg_off_func(void);
Expand Down
Loading

0 comments on commit 6d2fa9f

Please sign in to comment.