2024-05-19 23:56:37 +00:00
|
|
|
#include "th03/main/playfld.hpp"
|
2019-11-21 20:53:24 +00:00
|
|
|
#include "th03/hardware/vram.hpp"
|
|
|
|
|
2022-02-10 03:39:40 +00:00
|
|
|
// Relative offset inside the SPRITE16 sprite area, with 0 corresponding to
|
|
|
|
// SPRITE16_OFFSET.
|
|
|
|
typedef uvram_byte_amount_t sprite16_offset_t;
|
|
|
|
|
2024-04-16 13:31:17 +00:00
|
|
|
extern struct {
|
|
|
|
vram_h_t h;
|
|
|
|
VRAMWord w;
|
|
|
|
|
|
|
|
void set(pixel_t w_, pixel_t h_) {
|
|
|
|
w = w_;
|
|
|
|
h = (h_ / 2);
|
|
|
|
}
|
|
|
|
} sprite16_put_size;
|
2024-04-16 14:05:19 +00:00
|
|
|
extern struct {
|
|
|
|
screen_x_t left;
|
|
|
|
screen_x_t right;
|
|
|
|
|
2024-05-19 23:56:37 +00:00
|
|
|
void reset(void) {
|
|
|
|
left = PLAYFIELD1_CLIP_LEFT;
|
|
|
|
right = PLAYFIELD2_CLIP_RIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Additional variants for static constants
|
|
|
|
void set_for_pid_0(void) {
|
|
|
|
left = PLAYFIELD1_CLIP_LEFT;
|
|
|
|
right = PLAYFIELD1_CLIP_RIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_for_pid_1(void) {
|
|
|
|
left = PLAYFIELD2_CLIP_LEFT;
|
|
|
|
right = PLAYFIELD2_CLIP_RIGHT;
|
|
|
|
}
|
2024-04-16 14:05:19 +00:00
|
|
|
} sprite16_clip;
|
|
|
|
|
|
|
|
#define sprite16_clip_set_for_pid(pid) { \
|
|
|
|
if(pid == 0) { \
|
|
|
|
sprite16_clip.set_for_pid_0(); \
|
|
|
|
} else { \
|
|
|
|
sprite16_clip.set_for_pid_1(); \
|
|
|
|
} \
|
|
|
|
}
|
[Decompilation] [th03] Sprite display calls
Yes, decompilation, of something that was so obviously originally
written in ASM. We're still left with two un-decompilable instructions
here, but I'm amazed at how nicely I was able to abstract away all of
the gory register details, leading to pretty clear, readable, and dare
I say *portable* code?! Turbo C++ was once again pretty helpful here:
• `static_cast<char>(_BX) = _AL` actually compiles into `MOV BL, AL`,
as you would have intended,
• and no-op assignments like _DI = _DI are optimized away, allowing
us to leave them in for clarity, so that we can have all parameter
assignments for the SPRITE16 display call in a single place.
I love this compiler.
Part of P0060, funded by Touhou Patch Center.
2019-11-22 21:25:41 +00:00
|
|
|
|
|
|
|
enum sprite16_put_func_t {
|
|
|
|
SPF_NORMAL = 0,
|
|
|
|
// Repeatedly draws the sprite to form a gapless column, starting from the
|
|
|
|
// top Y coordinate given to sprite16_putx() down to the bottom of VRAM.
|
|
|
|
SPF_DOWNWARDS_COLUMN = 24,
|
2020-03-29 15:08:04 +00:00
|
|
|
|
2020-09-12 08:17:55 +00:00
|
|
|
_sprite16_put_func_t_FORCE_UINT16 = 0xFFFF
|
[Decompilation] [th03] Sprite display calls
Yes, decompilation, of something that was so obviously originally
written in ASM. We're still left with two un-decompilable instructions
here, but I'm amazed at how nicely I was able to abstract away all of
the gory register details, leading to pretty clear, readable, and dare
I say *portable* code?! Turbo C++ was once again pretty helpful here:
• `static_cast<char>(_BX) = _AL` actually compiles into `MOV BL, AL`,
as you would have intended,
• and no-op assignments like _DI = _DI are optimized away, allowing
us to leave them in for clarity, so that we can have all parameter
assignments for the SPRITE16 display call in a single place.
I love this compiler.
Part of P0060, funded by Touhou Patch Center.
2019-11-22 21:25:41 +00:00
|
|
|
};
|
|
|
|
|
2024-05-26 17:39:06 +00:00
|
|
|
extern "C" {
|
|
|
|
|
2020-09-06 11:14:43 +00:00
|
|
|
// Copies the entire sprite area in VRAM from page [dst_page ^ 1] to
|
|
|
|
// [dst_page]. Returns true if successful, false if the temporary memory
|
|
|
|
// couldn't be allocated.
|
|
|
|
bool16 pascal sprite16_sprites_copy_page(int dst_page);
|
|
|
|
|
|
|
|
// Initializes SPRITE16 for double-buffered blitting of the sprites that have
|
|
|
|
// been blitted to the sprite area on VRAM page 0.
|
|
|
|
void pascal sprite16_sprites_commit(void);
|
|
|
|
|
|
|
|
// Draws the sprite with the given offset in the SPRITE16 sprite area at the
|
[Decompilation] [th03] Sprite display calls
Yes, decompilation, of something that was so obviously originally
written in ASM. We're still left with two un-decompilable instructions
here, but I'm amazed at how nicely I was able to abstract away all of
the gory register details, leading to pretty clear, readable, and dare
I say *portable* code?! Turbo C++ was once again pretty helpful here:
• `static_cast<char>(_BX) = _AL` actually compiles into `MOV BL, AL`,
as you would have intended,
• and no-op assignments like _DI = _DI are optimized away, allowing
us to leave them in for clarity, so that we can have all parameter
assignments for the SPRITE16 display call in a single place.
I love this compiler.
Part of P0060, funded by Touhou Patch Center.
2019-11-22 21:25:41 +00:00
|
|
|
// given (left, top) position in screen (not VRAM) coordinates. The left and
|
|
|
|
// right parts of the sprite are clipped in 16-pixel increments to stay within
|
|
|
|
// the left and right clipping points, so make sure to hide at least 16 more
|
|
|
|
// pixels right of `sprite16_clip_left` and left of `sprite16_clip_right` on
|
|
|
|
// purpose.
|
2022-02-10 03:39:40 +00:00
|
|
|
void pascal sprite16_put(screen_x_t left, screen_y_t top, sprite16_offset_t so);
|
2022-08-09 21:23:54 +00:00
|
|
|
|
[Decompilation] [th03] Sprite display calls
Yes, decompilation, of something that was so obviously originally
written in ASM. We're still left with two un-decompilable instructions
here, but I'm amazed at how nicely I was able to abstract away all of
the gory register details, leading to pretty clear, readable, and dare
I say *portable* code?! Turbo C++ was once again pretty helpful here:
• `static_cast<char>(_BX) = _AL` actually compiles into `MOV BL, AL`,
as you would have intended,
• and no-op assignments like _DI = _DI are optimized away, allowing
us to leave them in for clarity, so that we can have all parameter
assignments for the SPRITE16 display call in a single place.
I love this compiler.
Part of P0060, funded by Touhou Patch Center.
2019-11-22 21:25:41 +00:00
|
|
|
// Like sprite16_put(), but using an optional drawing function.
|
|
|
|
void pascal sprite16_putx(
|
2022-02-10 03:39:40 +00:00
|
|
|
screen_x_t left,
|
|
|
|
screen_y_t top,
|
|
|
|
sprite16_offset_t so,
|
|
|
|
sprite16_put_func_t func
|
[Decompilation] [th03] Sprite display calls
Yes, decompilation, of something that was so obviously originally
written in ASM. We're still left with two un-decompilable instructions
here, but I'm amazed at how nicely I was able to abstract away all of
the gory register details, leading to pretty clear, readable, and dare
I say *portable* code?! Turbo C++ was once again pretty helpful here:
• `static_cast<char>(_BX) = _AL` actually compiles into `MOV BL, AL`,
as you would have intended,
• and no-op assignments like _DI = _DI are optimized away, allowing
us to leave them in for clarity, so that we can have all parameter
assignments for the SPRITE16 display call in a single place.
I love this compiler.
Part of P0060, funded by Touhou Patch Center.
2019-11-22 21:25:41 +00:00
|
|
|
);
|
2022-08-09 21:23:54 +00:00
|
|
|
|
[Decompilation] [th03] Sprite display calls
Yes, decompilation, of something that was so obviously originally
written in ASM. We're still left with two un-decompilable instructions
here, but I'm amazed at how nicely I was able to abstract away all of
the gory register details, leading to pretty clear, readable, and dare
I say *portable* code?! Turbo C++ was once again pretty helpful here:
• `static_cast<char>(_BX) = _AL` actually compiles into `MOV BL, AL`,
as you would have intended,
• and no-op assignments like _DI = _DI are optimized away, allowing
us to leave them in for clarity, so that we can have all parameter
assignments for the SPRITE16 display call in a single place.
I love this compiler.
Part of P0060, funded by Touhou Patch Center.
2019-11-22 21:25:41 +00:00
|
|
|
// Like sprite16_put(), but ignores the clipping points.
|
2020-08-20 19:59:45 +00:00
|
|
|
void pascal sprite16_put_noclip(
|
2022-02-10 03:39:40 +00:00
|
|
|
screen_x_t left, screen_y_t top, sprite16_offset_t so
|
2020-08-20 19:59:45 +00:00
|
|
|
);
|
2024-05-26 17:39:06 +00:00
|
|
|
|
|
|
|
}
|