Compare commits
10 Commits
7ec3ec5480
...
dd8c1010c5
Author | SHA1 | Date | |
---|---|---|---|
dd8c1010c5 | |||
50173b96e3 | |||
fb041b392c | |||
a1707c72a8 | |||
863701941e | |||
72bdd34675 | |||
2eef2be39e | |||
fb0b237e0c | |||
5f290a3e93 | |||
511bfd1d0c |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
*.d
|
||||||
*.gch
|
*.gch
|
||||||
*.o
|
*.o
|
||||||
*.elf
|
*.elf
|
||||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 saturn-examples contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
18
Makefile
18
Makefile
@ -17,6 +17,7 @@ ALL += wordle/wordle.cue
|
|||||||
ALL += scsp/slot.cue
|
ALL += scsp/slot.cue
|
||||||
ALL += scsp/sound_cpu__slot.cue
|
ALL += scsp/sound_cpu__slot.cue
|
||||||
ALL += scsp/sound_cpu__interrupt.cue
|
ALL += scsp/sound_cpu__interrupt.cue
|
||||||
|
ALL += scsp/sound_cpu__midi_debug.cue
|
||||||
ALL += editor/main_saturn.cue
|
ALL += editor/main_saturn.cue
|
||||||
|
|
||||||
all: $(ALL)
|
all: $(ALL)
|
||||||
@ -26,6 +27,12 @@ include $(LIB)/common.mk
|
|||||||
%.data.o: %.data
|
%.data.o: %.data
|
||||||
$(BUILD_BINARY_O)
|
$(BUILD_BINARY_O)
|
||||||
|
|
||||||
|
%.pattern.o: %.pattern
|
||||||
|
$(BUILD_BINARY_O)
|
||||||
|
|
||||||
|
%.tile.o: %.tile
|
||||||
|
$(BUILD_BINARY_O)
|
||||||
|
|
||||||
%.bin.o: %.bin
|
%.bin.o: %.bin
|
||||||
$(BUILD_BINARY_O)
|
$(BUILD_BINARY_O)
|
||||||
|
|
||||||
@ -44,8 +51,11 @@ vdp2/nbg0.elf: vdp2/nbg0.o res/butterfly.data.o res/butterfly.data.pal.o
|
|||||||
|
|
||||||
vdp2/nbg0_16color.elf: vdp2/nbg0_16color.o res/kirby.data.o res/kirby.data.pal.o
|
vdp2/nbg0_16color.elf: vdp2/nbg0_16color.o res/kirby.data.o res/kirby.data.pal.o
|
||||||
|
|
||||||
|
vdp2/color_calculation_ratio.elf: vdp2/color_calculation_ratio.o res/mai00.data.o res/mai.data.pal.o res/haohmaru.data.o res/haohmaru.data.pal.o res/forest.data.pal.o res/forest.pattern.o res/forest.tile.o
|
||||||
|
|
||||||
vdp1/polygon.elf: vdp1/polygon.o
|
vdp1/polygon.elf: vdp1/polygon.o
|
||||||
vdp1/cube.elf: vdp1/cube.o $(LIBGCC)
|
vdp1/cube.elf: vdp1/cube.o $(LIBGCC)
|
||||||
|
vdp1/cube2.elf: vdp1/cube2.o
|
||||||
vdp1/normal_sprite.elf: vdp1/normal_sprite.o res/mai00.data.o res/mai.data.pal.o
|
vdp1/normal_sprite.elf: vdp1/normal_sprite.o res/mai00.data.o res/mai.data.pal.o
|
||||||
|
|
||||||
vdp1/normal_sprite_color_bank.elf: vdp1/normal_sprite_color_bank.o res/mai00.data.o res/mai.data.pal.o
|
vdp1/normal_sprite_color_bank.elf: vdp1/normal_sprite_color_bank.o res/mai00.data.o res/mai.data.pal.o
|
||||||
@ -81,7 +91,7 @@ common/keyboard.hpp: common/keyboard.py
|
|||||||
common/keyboard.cpp: common/keyboard.py common/keyboard.hpp
|
common/keyboard.cpp: common/keyboard.py common/keyboard.hpp
|
||||||
python common/keyboard.py definition > $@
|
python common/keyboard.py definition > $@
|
||||||
|
|
||||||
smpc/input_keyboard.o: common/keyboard.hpp
|
smpc/input_keyboard.cpp.d: common/keyboard.hpp
|
||||||
|
|
||||||
smpc/input_keyboard.elf: smpc/input_keyboard.o sh/lib1funcs.o res/dejavusansmono.font.bin.o common/keyboard.o common/draw_font.o common/palette.o
|
smpc/input_keyboard.elf: smpc/input_keyboard.o sh/lib1funcs.o res/dejavusansmono.font.bin.o common/keyboard.o common/draw_font.o common/palette.o
|
||||||
|
|
||||||
@ -90,7 +100,7 @@ wordle/main_saturn.o: common/keyboard.hpp
|
|||||||
wordle/word_list.hpp: wordle/word_list.csv wordle/word_list.py
|
wordle/word_list.hpp: wordle/word_list.csv wordle/word_list.py
|
||||||
python wordle/word_list.py > $@
|
python wordle/word_list.py > $@
|
||||||
|
|
||||||
wordle/wordle.o: wordle/word_list.hpp
|
wordle/wordle.cpp.d: wordle/word_list.hpp
|
||||||
|
|
||||||
wordle/wordle.elf: wordle/main_saturn.o wordle/wordle.o wordle/draw.o sh/lib1funcs.o res/dejavusansmono.font.bin.o common/keyboard.o common/draw_font.o common/palette.o
|
wordle/wordle.elf: wordle/main_saturn.o wordle/wordle.o wordle/draw.o sh/lib1funcs.o res/dejavusansmono.font.bin.o common/keyboard.o common/draw_font.o common/palette.o
|
||||||
|
|
||||||
@ -121,6 +131,8 @@ scsp/sound_cpu__slot.elf: scsp/sound_cpu__slot.o m68k/slot.bin.o
|
|||||||
|
|
||||||
scsp/sound_cpu__interrupt.elf: scsp/sound_cpu__interrupt.o m68k/interrupt.bin.o sh/lib1funcs.o res/sperrypc.font.bin.o common/draw_font.o common/palette.o
|
scsp/sound_cpu__interrupt.elf: scsp/sound_cpu__interrupt.o m68k/interrupt.bin.o sh/lib1funcs.o res/sperrypc.font.bin.o common/draw_font.o common/palette.o
|
||||||
|
|
||||||
|
scsp/sound_cpu__midi_debug.elf: scsp/sound_cpu__midi_debug.o m68k/midi_debug.bin.o sh/lib1funcs.o res/nec.bitmap.bin.o
|
||||||
|
|
||||||
scsp/fm.elf: scsp/fm.o res/nec.bitmap.bin.o sh/lib1funcs.o saturn/start.o scsp/sine-44100-s16be-1ch-100sample.pcm.o
|
scsp/fm.elf: scsp/fm.o res/nec.bitmap.bin.o sh/lib1funcs.o saturn/start.o scsp/sine-44100-s16be-1ch-100sample.pcm.o
|
||||||
|
|
||||||
scsp/sound_cpu__midi.elf: scsp/sound_cpu__midi.o m68k/midi.bin.o res/nec.bitmap.bin.o sh/lib1funcs.o saturn/start.o
|
scsp/sound_cpu__midi.elf: scsp/sound_cpu__midi.o m68k/midi.bin.o res/nec.bitmap.bin.o sh/lib1funcs.o saturn/start.o
|
||||||
@ -145,7 +157,7 @@ clean-sh:
|
|||||||
-not -path './saturn/*' \
|
-not -path './saturn/*' \
|
||||||
-not -path './tools/*' \
|
-not -path './tools/*' \
|
||||||
-regextype posix-egrep \
|
-regextype posix-egrep \
|
||||||
-regex '.*\.(iso|o|bin|elf|cue)$$' \
|
-regex '.*\.(iso|o|bin|elf|cue|gch)$$' \
|
||||||
-exec rm {} \;
|
-exec rm {} \;
|
||||||
rm -f \
|
rm -f \
|
||||||
common/keyboard.cpp \
|
common/keyboard.cpp \
|
||||||
|
@ -325,8 +325,8 @@ void main()
|
|||||||
2-word: value of bit 5-0 * 0x4000
|
2-word: value of bit 5-0 * 0x4000
|
||||||
*/
|
*/
|
||||||
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
||||||
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0
|
vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0
|
||||||
vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0
|
||||||
|
|
||||||
// zeroize character/cell data from 0 up to plane_a_offset
|
// zeroize character/cell data from 0 up to plane_a_offset
|
||||||
fill<uint32_t>(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a));
|
fill<uint32_t>(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a));
|
||||||
|
@ -15,6 +15,14 @@ include $(LIB)/m68k/common.mk
|
|||||||
synth 101s $* 441 vol -10dB
|
synth 101s $* 441 vol -10dB
|
||||||
mv $@.raw $@
|
mv $@.raw $@
|
||||||
|
|
||||||
|
# 88200 bytes
|
||||||
|
%-44100-s16be-1ch-1sec.pcm: Makefile
|
||||||
|
sox \
|
||||||
|
-r 44100 -e signed-integer -b 16 -c 1 -n -B \
|
||||||
|
$@.raw \
|
||||||
|
synth 1 sin 440 vol -10dB
|
||||||
|
mv $@.raw $@
|
||||||
|
|
||||||
%.pcm.o: %.pcm
|
%.pcm.o: %.pcm
|
||||||
$(BUILD_BINARY_O)
|
$(BUILD_BINARY_O)
|
||||||
|
|
||||||
@ -26,3 +34,5 @@ slot.elf: slot.o sine-44100-s16be-1ch-1sec.pcm.o
|
|||||||
interrupt.elf: interrupt.o jojo-11025-s16be-1ch.pcm.o
|
interrupt.elf: interrupt.o jojo-11025-s16be-1ch.pcm.o
|
||||||
|
|
||||||
midi.elf: midi.o sine-44100-s16be-1ch-100sample.pcm.o midi_test-c-major-scale.mid.o f2.mid.o ../midi/parse.o $(LIBGCC)
|
midi.elf: midi.o sine-44100-s16be-1ch-100sample.pcm.o midi_test-c-major-scale.mid.o f2.mid.o ../midi/parse.o $(LIBGCC)
|
||||||
|
|
||||||
|
midi_debug.elf: midi_debug.o
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
extern void * _jojo_start __asm("_binary_jojo_11025_s16be_1ch_pcm_start");
|
extern void * _jojo_start __asm("_binary_jojo_11025_s16be_1ch_pcm_start");
|
||||||
|
|
||||||
static volatile int32_t frame = 0x0;
|
static int32_t frame = 0x0;
|
||||||
|
|
||||||
constexpr int32_t tactl = 7;
|
constexpr int32_t tactl = 7;
|
||||||
constexpr int32_t frame_size = ((1 << tactl) * 256) / (44100 / 11025);
|
constexpr int32_t frame_size = ((1 << tactl) * 256) / (44100 / 11025);
|
||||||
|
24
m68k/midi_debug.cpp
Normal file
24
m68k/midi_debug.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "scsp.h"
|
||||||
|
|
||||||
|
static uint32_t ram_ix = 0;
|
||||||
|
|
||||||
|
static uint16_t * debug_buf = &scsp.ram.u16[0x080000 / 2];
|
||||||
|
static uint16_t * debug_length = &scsp.ram.u16[(0x080000 / 4) - 2];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
*debug_length = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
uint16_t midiu = scsp.reg.ctrl.MIDIU;
|
||||||
|
uint16_t mibuf = MIDIU__MIBUF(midiu);
|
||||||
|
uint16_t miemp = midiu & MIDIU__MIEMP;
|
||||||
|
if (miemp) continue;
|
||||||
|
|
||||||
|
(*debug_length)++;
|
||||||
|
(*debug_buf) = mibuf;
|
||||||
|
debug_buf++;
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "scsp.h"
|
#include "scsp.h"
|
||||||
|
|
||||||
extern void * _sine_start __asm("_binary_sine_44100_s16be_1ch_pcm_start");
|
extern void * _sine_start __asm("_binary_sine_44100_s16be_1ch_1sec_pcm_start");
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,7 @@ struct vec<4, T>
|
|||||||
inline constexpr vec();
|
inline constexpr vec();
|
||||||
inline constexpr vec(T scalar);
|
inline constexpr vec(T scalar);
|
||||||
inline constexpr vec(T _x, T _y, T _z, T _w);
|
inline constexpr vec(T _x, T _y, T _z, T _w);
|
||||||
|
inline constexpr vec(vec<3, T> const& xyz, T w);
|
||||||
|
|
||||||
constexpr inline vec<4, T> operator-() const;
|
constexpr inline vec<4, T> operator-() const;
|
||||||
inline constexpr T const& operator[](int i) const;
|
inline constexpr T const& operator[](int i) const;
|
||||||
@ -34,8 +35,13 @@ inline constexpr vec<4, T>::vec(T scalar)
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr vec<4, T>::vec(T _x, T _y, T _z, T _w)
|
inline constexpr vec<4, T>::vec(T x, T y, T z, T w)
|
||||||
: x(_x), y(_y), z(_z), w(_w)
|
: x(x), y(y), z(z), w(w)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr vec<4, T>::vec(vec<3, T> const& xyz, T w)
|
||||||
|
: x(xyz.x), y(xyz.y), z(xyz.z), w(w)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#include "smpc.h"
|
#include "smpc.h"
|
||||||
#include "sh2.h"
|
#include "sh2.h"
|
||||||
|
|
||||||
#include "vec.hpp"
|
#include "../math/vec3.hpp"
|
||||||
#include "fp.hpp"
|
#include "../math/fp.hpp"
|
||||||
#include "raytracing.hpp"
|
#include "raytracing.hpp"
|
||||||
|
|
||||||
constexpr inline
|
constexpr inline
|
||||||
@ -22,9 +22,9 @@ inline constexpr T rgb(const vec3& color)
|
|||||||
|
|
||||||
vec3 c = functor1(clamp, color) * fp16_16(channel_mask);
|
vec3 c = functor1(clamp, color) * fp16_16(channel_mask);
|
||||||
|
|
||||||
T red = static_cast<T>(c.r.value >> 16);
|
T red = static_cast<T>(c.x.value >> 16);
|
||||||
T green = static_cast<T>(c.g.value >> 16);
|
T green = static_cast<T>(c.y.value >> 16);
|
||||||
T blue = static_cast<T>(c.b.value >> 16);
|
T blue = static_cast<T>(c.z.value >> 16);
|
||||||
|
|
||||||
return (1 << last_bit)
|
return (1 << last_bit)
|
||||||
| (blue << (P * 2))
|
| (blue << (P * 2))
|
||||||
@ -84,7 +84,8 @@ void start_slave()
|
|||||||
*/
|
*/
|
||||||
sh2_vec[0x94] = (uint32_t)(&slave_main);
|
sh2_vec[0x94] = (uint32_t)(&slave_main);
|
||||||
|
|
||||||
for (volatile int i = 0; i < 10; i++);
|
for (int i = 0; i < 10; i++)
|
||||||
|
asm volatile ("nop");
|
||||||
|
|
||||||
smpc.reg.SF = 1;
|
smpc.reg.SF = 1;
|
||||||
smpc.reg.COMREG = COMREG__SSHON;
|
smpc.reg.COMREG = COMREG__SSHON;
|
||||||
@ -92,7 +93,7 @@ void start_slave()
|
|||||||
while ((smpc.reg.SF & 0x01) == 1);
|
while ((smpc.reg.SF & 0x01) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main_asdf()
|
void main()
|
||||||
{
|
{
|
||||||
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
|
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
|
||||||
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
||||||
@ -131,10 +132,3 @@ void main_asdf()
|
|||||||
|
|
||||||
render(0, put_pixel);
|
render(0, put_pixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main_asdf();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "vec.hpp"
|
#include "vec3.hpp"
|
||||||
#include "fp.hpp"
|
#include "fp.hpp"
|
||||||
#include "raytracing.hpp"
|
#include "raytracing.hpp"
|
||||||
|
|
||||||
namespace viewport {
|
vec3 canvas_to_viewport(const int cx, const int cy)
|
||||||
constexpr int width = 1;
|
|
||||||
constexpr int height = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 canvas_to_viewport(int cx, int cy)
|
|
||||||
{
|
{
|
||||||
return vec3(
|
return vec3(fp16_16(cx * viewport::width) / fp16_16(canvas::square_width),
|
||||||
fp16_16(((cx * viewport::width) * (1 << 16)) >> canvas::bit_width, fp_raw_tag{}),
|
fp16_16(cy * viewport::height) / fp16_16(canvas::square_height),
|
||||||
fp16_16(((cy * viewport::height) * (1 << 16)) >> canvas::bit_height, fp_raw_tag{}),
|
|
||||||
fp16_16(1)
|
fp16_16(1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -53,44 +47,44 @@ constexpr scene scene {
|
|||||||
1, // radius
|
1, // radius
|
||||||
{1, 0, 0}, // color
|
{1, 0, 0}, // color
|
||||||
8, // specular
|
8, // specular
|
||||||
fp16_16(65536 * 0.2, fp_raw_tag{}) // reflective
|
fp16_16(0.2) // reflective
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{2, 0, 4},
|
{2, 0, 4},
|
||||||
1,
|
1,
|
||||||
{0, 0, 1},
|
{0, 0, 1},
|
||||||
10,
|
10,
|
||||||
fp16_16(65536 * 0.3, fp_raw_tag{})
|
fp16_16(0.3)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{-2, 0, 4},
|
{-2, 0, 4},
|
||||||
fp16_16(1),
|
fp16_16(1),
|
||||||
{0, 1, 0},
|
{0, 1, 0},
|
||||||
10,
|
10,
|
||||||
fp16_16(65536 * 0.4, fp_raw_tag{})
|
fp16_16(0.4)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{0, -31, 0},
|
{0, -31, 0},
|
||||||
fp16_16(30),
|
fp16_16(30),
|
||||||
{1, 1, 0},
|
{1, 1, 0},
|
||||||
0,
|
0,
|
||||||
fp16_16(65536 * 0.5, fp_raw_tag{})
|
fp16_16(0.5)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ // lights
|
{ // lights
|
||||||
{
|
{
|
||||||
light_type::ambient, // type
|
light_type::ambient, // type
|
||||||
fp16_16(65536 * 0.2, fp_raw_tag{}), // intensity
|
fp16_16(0.2), // intensity
|
||||||
{{0, 0, 0}} //
|
{{0, 0, 0}} //
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
light_type::point, // type
|
light_type::point, // type
|
||||||
fp16_16(65536 * 0.6, fp_raw_tag{}), // intensity
|
fp16_16(0.6), // intensity
|
||||||
{{2, 1, 0}} // position
|
{{2, 1, 0}} // position
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
light_type::directional, // type
|
light_type::directional, // type
|
||||||
fp16_16(65536 * 0.6, fp_raw_tag{}), // intensity
|
fp16_16(0.6), // intensity
|
||||||
{{1, 4, 4}} // direction
|
{{1, 4, 4}} // direction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,7 +173,7 @@ fp16_16 compute_lighting(const vec3& point, const vec3& normal,
|
|||||||
t_max = fp_limits<fp16_16>::max();
|
t_max = fp_limits<fp16_16>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr fp16_16 t_min = fp16_16(128, fp_raw_tag{});
|
constexpr fp16_16 t_min = fp16_16(128.f / 65536.f);
|
||||||
auto [shadow_t, shadow_sphere] = closest_intersection(point, light_vector, t_min, t_max);
|
auto [shadow_t, shadow_sphere] = closest_intersection(point, light_vector, t_min, t_max);
|
||||||
if (shadow_sphere != nullptr)
|
if (shadow_sphere != nullptr)
|
||||||
continue;
|
continue;
|
||||||
@ -235,7 +229,7 @@ static vec3 trace_ray
|
|||||||
} else {
|
} else {
|
||||||
auto reflected_ray = reflect_ray(direction_neg, normal);
|
auto reflected_ray = reflect_ray(direction_neg, normal);
|
||||||
auto reflected_color = trace_ray(point, reflected_ray,
|
auto reflected_color = trace_ray(point, reflected_ray,
|
||||||
fp16_16(128, fp_raw_tag{}),
|
fp16_16(128.f / 65536.f),
|
||||||
fp_limits<fp16_16>::max(),
|
fp_limits<fp16_16>::max(),
|
||||||
recursion_depth - 1);
|
recursion_depth - 1);
|
||||||
return local_color * (fp16_16(1) - reflective) + reflected_color * reflective;
|
return local_color * (fp16_16(1) - reflective) + reflected_color * reflective;
|
||||||
@ -245,16 +239,13 @@ static vec3 trace_ray
|
|||||||
|
|
||||||
void render(int half, void (&put_pixel) (int32_t x, int32_t y, const vec3& c))
|
void render(int half, void (&put_pixel) (int32_t x, int32_t y, const vec3& c))
|
||||||
{
|
{
|
||||||
using namespace canvas;
|
|
||||||
|
|
||||||
vec3 origin = vec3(0, 0, 0);
|
vec3 origin = vec3(0, 0, 0);
|
||||||
|
|
||||||
int x_low = half ? 0 : -(320/2);
|
int x_low = half ? 0 : -(canvas::width/2);
|
||||||
int x_high = half ? (320/2) : 0;
|
int x_high = half ? (canvas::width/2) : 0;
|
||||||
|
|
||||||
//for (int x = -(width/2); x < (width/2); x++) {
|
|
||||||
for (int x = x_low; x < x_high; x++) {
|
for (int x = x_low; x < x_high; x++) {
|
||||||
for (int y = -(height/2 + 1); y < (height/2 + 1); y++) {
|
for (int y = -(canvas::height/2 + 1); y < (canvas::height/2 + 1); y++) {
|
||||||
vec3 direction = canvas_to_viewport(x, y);
|
vec3 direction = canvas_to_viewport(x, y);
|
||||||
vec3 color = trace_ray(origin, direction,
|
vec3 color = trace_ray(origin, direction,
|
||||||
fp16_16(1),
|
fp16_16(1),
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fp.hpp"
|
#include "../math/fp.hpp"
|
||||||
#include "raytracing.hpp"
|
#include "raytracing.hpp"
|
||||||
|
|
||||||
using vec3 = vec<3, fp16_16>;
|
using vec3 = vec<3, fp16_16>;
|
||||||
|
|
||||||
|
namespace viewport {
|
||||||
|
constexpr int width = 1;
|
||||||
|
constexpr int height = 1;
|
||||||
|
}
|
||||||
|
|
||||||
namespace canvas {
|
namespace canvas {
|
||||||
constexpr int bit_width = 8;
|
constexpr int square_width = 256;
|
||||||
constexpr int bit_height = 8;
|
constexpr int square_height = 256;
|
||||||
constexpr int width = (1 << bit_width);
|
constexpr int width = 320;
|
||||||
constexpr int height = (1 << bit_height);
|
constexpr int height = 240;
|
||||||
}
|
}
|
||||||
|
|
||||||
void render(int half, void (&put_pixel) (int32_t x, int32_t y, const vec3& c));
|
void render(int half, void (&put_pixel) (int32_t x, int32_t y, const vec3& c));
|
||||||
|
BIN
res/forest.data
Normal file
BIN
res/forest.data
Normal file
Binary file not shown.
BIN
res/forest.data.pal
Normal file
BIN
res/forest.data.pal
Normal file
Binary file not shown.
BIN
res/forest.pattern
Normal file
BIN
res/forest.pattern
Normal file
Binary file not shown.
3
res/forest.tile
Normal file
3
res/forest.tile
Normal file
File diff suppressed because one or more lines are too long
BIN
res/forest.xcf
Normal file
BIN
res/forest.xcf
Normal file
Binary file not shown.
BIN
res/haohmaru.data
Normal file
BIN
res/haohmaru.data
Normal file
Binary file not shown.
BIN
res/haohmaru.data.pal
Normal file
BIN
res/haohmaru.data.pal
Normal file
Binary file not shown.
BIN
res/haohmaru.xcf
Normal file
BIN
res/haohmaru.xcf
Normal file
Binary file not shown.
@ -740,7 +740,7 @@ void main()
|
|||||||
*/
|
*/
|
||||||
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
||||||
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0
|
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0
|
||||||
vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(0) | MPCDN0__N0MPC(0); // bits 5~0
|
||||||
|
|
||||||
// zeroize character/cell data from 0 up to plane_a_offset
|
// zeroize character/cell data from 0 up to plane_a_offset
|
||||||
fill<uint32_t>(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a));
|
fill<uint32_t>(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a));
|
||||||
|
@ -33,10 +33,3 @@ void main()
|
|||||||
|
|
||||||
slot.LOOP |= LOOP__KYONEX;
|
slot.LOOP |= LOOP__KYONEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
@ -239,10 +239,3 @@ void main()
|
|||||||
|
|
||||||
init_sound();
|
init_sound();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
@ -240,7 +240,7 @@ void v_blank_in_int()
|
|||||||
scu.reg.IMS = ~(IMS__SMPC | IMS__V_BLANK_IN);
|
scu.reg.IMS = ~(IMS__SMPC | IMS__V_BLANK_IN);
|
||||||
|
|
||||||
// flip planes;
|
// flip planes;
|
||||||
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a + plane_ix);
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPB(0) | MPCDN0__N0MPA(plane_a + plane_ix);
|
||||||
//plane_ix = !plane_ix;
|
//plane_ix = !plane_ix;
|
||||||
|
|
||||||
// wait at least 300us, as specified in the SMPC manual.
|
// wait at least 300us, as specified in the SMPC manual.
|
||||||
@ -355,8 +355,8 @@ void main()
|
|||||||
2-word: value of bit 5-0 * 0x4000
|
2-word: value of bit 5-0 * 0x4000
|
||||||
*/
|
*/
|
||||||
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
||||||
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPB(0) | MPCDN0__N0MPA(plane_a); // bits 5~0
|
||||||
vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(0) | MPCDN0__N0MPC(0); // bits 5~0
|
||||||
|
|
||||||
// zeroize character/cell data from 0 up to plane_a_offset
|
// zeroize character/cell data from 0 up to plane_a_offset
|
||||||
fill<uint32_t>(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a));
|
fill<uint32_t>(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a));
|
||||||
|
204
scsp/sound_cpu__midi_debug.cpp
Normal file
204
scsp/sound_cpu__midi_debug.cpp
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "vdp2.h"
|
||||||
|
#include "smpc.h"
|
||||||
|
#include "scsp.h"
|
||||||
|
#include "scu.h"
|
||||||
|
#include "sh2.h"
|
||||||
|
|
||||||
|
#include "../common/copy.hpp"
|
||||||
|
#include "../common/vdp2_func.hpp"
|
||||||
|
#include "../common/string.hpp"
|
||||||
|
|
||||||
|
extern void * _nec_bitmap_start __asm("_binary_res_nec_bitmap_bin_start");
|
||||||
|
|
||||||
|
extern void * _m68k_start __asm("_binary_m68k_midi_debug_bin_start");
|
||||||
|
extern void * _m68k_size __asm("_binary_m68k_midi_debug_bin_size");
|
||||||
|
|
||||||
|
constexpr inline uint16_t rgb15(int32_t r, int32_t g, int32_t b)
|
||||||
|
{
|
||||||
|
return ((b & 31) << 10) | ((g & 31) << 5) | ((r & 31) << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void palette_data()
|
||||||
|
{
|
||||||
|
vdp2.cram.u16[1 + 0 ] = rgb15( 0, 0, 0);
|
||||||
|
vdp2.cram.u16[2 + 0 ] = rgb15(31, 31, 31);
|
||||||
|
|
||||||
|
vdp2.cram.u16[1 + 16] = rgb15(31, 31, 31);
|
||||||
|
vdp2.cram.u16[2 + 16] = rgb15( 0, 0, 0);
|
||||||
|
|
||||||
|
vdp2.cram.u16[1 + 32] = rgb15(10, 10, 10);
|
||||||
|
vdp2.cram.u16[2 + 32] = rgb15(31, 31, 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace pix_fmt_4bpp
|
||||||
|
{
|
||||||
|
constexpr inline uint32_t
|
||||||
|
bit(uint8_t n, int32_t i)
|
||||||
|
{
|
||||||
|
i &= 7;
|
||||||
|
auto b = (n >> (7 - i)) & 1;
|
||||||
|
return ((b + 1) << ((7 - i) * 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline uint32_t
|
||||||
|
bits(uint8_t n)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
bit(n, 0) | bit(n, 1) | bit(n, 2) | bit(n, 3)
|
||||||
|
| bit(n, 4) | bit(n, 5) | bit(n, 6) | bit(n, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(bits(0b1100'1110) == 0x2211'2221);
|
||||||
|
static_assert(bits(0b1010'0101) == 0x2121'1212);
|
||||||
|
static_assert(bits(0b1000'0000) == 0x2111'1111);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cell_data()
|
||||||
|
{
|
||||||
|
const uint8_t * normal = reinterpret_cast<uint8_t*>(&_nec_bitmap_start);
|
||||||
|
|
||||||
|
for (int ix = 0; ix <= (0x7f - 0x20); ix++) {
|
||||||
|
for (int y = 0; y < 8; y++) {
|
||||||
|
const uint8_t row_n = normal[ix * 8 + y];
|
||||||
|
vdp2.vram.u32[ 0 + (ix * 8) + y] = pix_fmt_4bpp::bits(row_n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int32_t plane_a = 2;
|
||||||
|
constexpr inline int32_t plane_offset(int32_t n) { return n * 0x2000; }
|
||||||
|
constexpr int32_t page_size = 64 * 64 * 2; // N0PNB__1WORD (16-bit)
|
||||||
|
constexpr int32_t plane_size = page_size * 1;
|
||||||
|
constexpr int32_t page_width = 64;
|
||||||
|
static int plane_ix = 0;
|
||||||
|
|
||||||
|
void init_vdp2()
|
||||||
|
{
|
||||||
|
v_blank_in();
|
||||||
|
|
||||||
|
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
|
||||||
|
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
||||||
|
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
|
||||||
|
|
||||||
|
/* set the color mode to 5bits per channel, 1024 colors */
|
||||||
|
vdp2.reg.RAMCTL = RAMCTL__CRMD__RGB_5BIT_1024;
|
||||||
|
|
||||||
|
/* enable display of NBG0 */
|
||||||
|
vdp2.reg.BGON = BGON__N0ON;
|
||||||
|
|
||||||
|
/* set character format for NBG0 to palettized 16 color
|
||||||
|
set enable "cell format" for NBG0
|
||||||
|
set character size for NBG0 to 1x1 cell */
|
||||||
|
vdp2.reg.CHCTLA = CHCTLA__N0CHCN__16_COLOR
|
||||||
|
| CHCTLA__N0BMEN__CELL_FORMAT
|
||||||
|
| CHCTLA__N0CHSZ__1x1_CELL;
|
||||||
|
/* "Note: In color RAM modes 0 and 2, 2048-color becomes 1024-color" */
|
||||||
|
|
||||||
|
/* use 1-word (16-bit) pattern names */
|
||||||
|
vdp2.reg.PNCN0 = PNCN0__N0PNB__1WORD;
|
||||||
|
|
||||||
|
/* plane size */
|
||||||
|
vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1;
|
||||||
|
|
||||||
|
/* map plane offset
|
||||||
|
1-word: value of bit 6-0 * 0x2000
|
||||||
|
2-word: value of bit 5-0 * 0x4000
|
||||||
|
*/
|
||||||
|
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
||||||
|
vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0
|
||||||
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0
|
||||||
|
|
||||||
|
// zeroize character/cell data from 0 up to plane_a_offset
|
||||||
|
fill<uint32_t>(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a));
|
||||||
|
|
||||||
|
// zeroize plane_a; `0` is the ascii 0x20 ("space") which doubles as
|
||||||
|
// "transparency" character.
|
||||||
|
fill<uint32_t>(&vdp2.vram.u32[(plane_offset(plane_a) / 4)], 0, plane_size * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_char(int32_t x, int32_t y, uint8_t palette, uint8_t c)
|
||||||
|
{
|
||||||
|
const auto ix = (plane_offset(plane_a + plane_ix) / 2) + (y * page_width) + x;
|
||||||
|
vdp2.vram.u16[ix] =
|
||||||
|
PATTERN_NAME_TABLE_1WORD__PALETTE(palette)
|
||||||
|
| PATTERN_NAME_TABLE_1WORD__CHARACTER((c - 0x20));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t * debug_buf = &scsp.ram.u16[0x080000 / 4];
|
||||||
|
static uint16_t * debug_length = &scsp.ram.u16[(0x080000 / 4) - 2];
|
||||||
|
|
||||||
|
void render()
|
||||||
|
{
|
||||||
|
static uint8_t lbuf[4];
|
||||||
|
string::hex(lbuf, 4, *debug_length);
|
||||||
|
for (uint32_t i = 0; i < 4; i++) set_char(i, 0, 0, lbuf[i]);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < *debug_length; i++) {
|
||||||
|
uint8_t buf[2];
|
||||||
|
string::hex(buf, 2, debug_buf[i]);
|
||||||
|
|
||||||
|
int32_t x = 1 + (i % 8);
|
||||||
|
int32_t y = 1 + (i / 8);
|
||||||
|
|
||||||
|
set_char(x * 3 + 0, y, 0, buf[0]);
|
||||||
|
set_char(x * 3 + 1, y, 0, buf[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
void v_blank_in_int(void) __attribute__ ((interrupt_handler));
|
||||||
|
void v_blank_in_int()
|
||||||
|
{
|
||||||
|
scu.reg.IST &= ~(IST__V_BLANK_IN);
|
||||||
|
scu.reg.IMS = ~(IMS__V_BLANK_IN);
|
||||||
|
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
/* SEGA SATURN TECHNICAL BULLETIN # 51
|
||||||
|
|
||||||
|
The document suggests that Sound RAM is (somewhat) preserved
|
||||||
|
during SNDOFF.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while ((smpc.reg.SF & 1) != 0);
|
||||||
|
smpc.reg.SF = 1;
|
||||||
|
smpc.reg.COMREG = COMREG__SNDOFF;
|
||||||
|
while (smpc.reg.OREG[31].val != OREG31__SNDOFF);
|
||||||
|
|
||||||
|
scsp.reg.ctrl.MIXER = MIXER__MEM4MB;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The Saturn BIOS does not (un)initialize the DSP. Without zeroizing the DSP
|
||||||
|
program, the SCSP DSP appears to have a program that continuously writes to
|
||||||
|
0x30000 through 0x3ffff in sound RAM, which has the effect of destroying any
|
||||||
|
samples stored there.
|
||||||
|
*/
|
||||||
|
reg32 * dsp_steps = reinterpret_cast<reg32*>(&(scsp.reg.dsp.STEP[0].MPRO[0]));
|
||||||
|
fill<reg32>(dsp_steps, 0, (sizeof (scsp.reg.dsp.STEP)));
|
||||||
|
|
||||||
|
uint32_t * m68k_main_start = reinterpret_cast<uint32_t*>(&_m68k_start);
|
||||||
|
uint32_t m68k_main_size = reinterpret_cast<uint32_t>(&_m68k_size);
|
||||||
|
copy<uint32_t>(&scsp.ram.u32[0], m68k_main_start, m68k_main_size);
|
||||||
|
|
||||||
|
while ((smpc.reg.SF & 1) != 0);
|
||||||
|
smpc.reg.SF = 1;
|
||||||
|
smpc.reg.COMREG = COMREG__SNDON;
|
||||||
|
while (smpc.reg.OREG[31].val != OREG31__SNDON);
|
||||||
|
|
||||||
|
// do nothing while the sound CPU manipulates the SCSP
|
||||||
|
|
||||||
|
init_vdp2();
|
||||||
|
palette_data();
|
||||||
|
cell_data();
|
||||||
|
|
||||||
|
sh2_vec[SCU_VEC__V_BLANK_IN] = (u32)(&v_blank_in_int);
|
||||||
|
|
||||||
|
scu.reg.IST = 0;
|
||||||
|
scu.reg.IMS = ~(IMS__V_BLANK_IN);
|
||||||
|
}
|
@ -43,10 +43,3 @@ void main()
|
|||||||
|
|
||||||
// do nothing while the sound CPU manipulates the SCSP
|
// do nothing while the sound CPU manipulates the SCSP
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
@ -330,7 +330,7 @@ void main()
|
|||||||
// It appears Kronos does not correctly calculate the color address in the
|
// It appears Kronos does not correctly calculate the color address in the
|
||||||
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
||||||
// in this example is 7FFE0.
|
// in this example is 7FFE0.
|
||||||
vdp1.vram.cmd[2].COLR = COLR__ADDRESS(color_address); // non-palettized (rgb15) color data
|
vdp1.vram.cmd[2].COLR = COLR__LOOKUP_TABLE__ADDRESS(color_address); // non-palettized (rgb15) color data
|
||||||
vdp1.vram.cmd[2].SRCA = SRCA(character_address[0]);
|
vdp1.vram.cmd[2].SRCA = SRCA(character_address[0]);
|
||||||
vdp1.vram.cmd[2].SIZE = SIZE__X(sprite_stride) | SIZE__Y(sprite_height);
|
vdp1.vram.cmd[2].SIZE = SIZE__X(sprite_stride) | SIZE__Y(sprite_height);
|
||||||
vdp1.vram.cmd[2].XA = foo[0].x;
|
vdp1.vram.cmd[2].XA = foo[0].x;
|
||||||
@ -345,7 +345,7 @@ void main()
|
|||||||
// It appears Kronos does not correctly calculate the color address in the
|
// It appears Kronos does not correctly calculate the color address in the
|
||||||
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
||||||
// in this example is 7FFE0.
|
// in this example is 7FFE0.
|
||||||
vdp1.vram.cmd[3].COLR = COLR__ADDRESS(color_address); // non-palettized (rgb15) color data
|
vdp1.vram.cmd[3].COLR = COLR__LOOKUP_TABLE__ADDRESS(color_address); // non-palettized (rgb15) color data
|
||||||
vdp1.vram.cmd[3].SRCA = SRCA(character_address[1]);
|
vdp1.vram.cmd[3].SRCA = SRCA(character_address[1]);
|
||||||
vdp1.vram.cmd[3].SIZE = SIZE__X(sprite_stride) | SIZE__Y(sprite_height);
|
vdp1.vram.cmd[3].SIZE = SIZE__X(sprite_stride) | SIZE__Y(sprite_height);
|
||||||
vdp1.vram.cmd[3].XA = foo[1].x;
|
vdp1.vram.cmd[3].XA = foo[1].x;
|
||||||
@ -373,10 +373,3 @@ void main()
|
|||||||
scu.reg.IST = 0;
|
scu.reg.IST = 0;
|
||||||
scu.reg.IMS &= ~(IMS__SMPC);
|
scu.reg.IMS &= ~(IMS__SMPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
@ -415,7 +415,7 @@ void main()
|
|||||||
// It appears Kronos does not correctly calculate the color address in the
|
// It appears Kronos does not correctly calculate the color address in the
|
||||||
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
||||||
// in this example is 7FFE0.
|
// in this example is 7FFE0.
|
||||||
vdp1.vram.cmd[2].COLR = COLR__ADDRESS(color_address); // non-palettized (rgb15) color data
|
vdp1.vram.cmd[2].COLR = COLR__LOOKUP_TABLE__ADDRESS(color_address); // non-palettized (rgb15) color data
|
||||||
vdp1.vram.cmd[2].SRCA = SRCA(character_address[0]);
|
vdp1.vram.cmd[2].SRCA = SRCA(character_address[0]);
|
||||||
vdp1.vram.cmd[2].SIZE = SIZE__X(sprite_stride) | SIZE__Y(sprite_height);
|
vdp1.vram.cmd[2].SIZE = SIZE__X(sprite_stride) | SIZE__Y(sprite_height);
|
||||||
vdp1.vram.cmd[2].XA = foo[0].x;
|
vdp1.vram.cmd[2].XA = foo[0].x;
|
||||||
@ -430,7 +430,7 @@ void main()
|
|||||||
// It appears Kronos does not correctly calculate the color address in the
|
// It appears Kronos does not correctly calculate the color address in the
|
||||||
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
||||||
// in this example is 7FFE0.
|
// in this example is 7FFE0.
|
||||||
vdp1.vram.cmd[3].COLR = COLR__ADDRESS(color_address); // non-palettized (rgb15) color data
|
vdp1.vram.cmd[3].COLR = COLR__LOOKUP_TABLE__ADDRESS(color_address); // non-palettized (rgb15) color data
|
||||||
vdp1.vram.cmd[3].SRCA = SRCA(character_address[1]);
|
vdp1.vram.cmd[3].SRCA = SRCA(character_address[1]);
|
||||||
vdp1.vram.cmd[3].SIZE = SIZE__X(sprite_stride) | SIZE__Y(sprite_height);
|
vdp1.vram.cmd[3].SIZE = SIZE__X(sprite_stride) | SIZE__Y(sprite_height);
|
||||||
vdp1.vram.cmd[3].XA = foo[1].x;
|
vdp1.vram.cmd[3].XA = foo[1].x;
|
||||||
@ -462,10 +462,3 @@ void main()
|
|||||||
scu.reg.IST = 0;
|
scu.reg.IST = 0;
|
||||||
scu.reg.IMS = ~(IMS__SMPC | IMS__V_BLANK_IN);
|
scu.reg.IMS = ~(IMS__SMPC | IMS__V_BLANK_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
68
tools/tile.py
Normal file
68
tools/tile.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
|
||||||
|
with open(sys.argv[1], 'rb') as f:
|
||||||
|
buf = f.read()
|
||||||
|
|
||||||
|
stride = 320
|
||||||
|
|
||||||
|
def get_tile(buf, tx, ty):
|
||||||
|
tile = []
|
||||||
|
for y in range(8):
|
||||||
|
row = []
|
||||||
|
for x in range(8):
|
||||||
|
yy = ty * 8 + y
|
||||||
|
xx = tx * 8 + x
|
||||||
|
ix = yy * stride + xx
|
||||||
|
px = buf[ix]
|
||||||
|
row.append(px)
|
||||||
|
tile.append(tuple(row))
|
||||||
|
return tuple(tile)
|
||||||
|
|
||||||
|
def tile_input(buf):
|
||||||
|
tiles = []
|
||||||
|
pattern = []
|
||||||
|
|
||||||
|
for ty in range(240 // 8):
|
||||||
|
for tx in range(320 // 8):
|
||||||
|
tile = get_tile(buf, tx, ty)
|
||||||
|
#if tile in tiles:
|
||||||
|
# pass
|
||||||
|
#else:
|
||||||
|
# tiles.append(tile)
|
||||||
|
#tile_ix = tiles.index(tile)
|
||||||
|
tiles.append(tile)
|
||||||
|
tile_ix = len(tiles) - 1
|
||||||
|
pattern.append(tile_ix)
|
||||||
|
|
||||||
|
return tiles, pattern
|
||||||
|
|
||||||
|
|
||||||
|
def emit_tile(tile):
|
||||||
|
for row in tile:
|
||||||
|
for ix in range(len(row) // 2):
|
||||||
|
a = row[ix * 2 + 0]
|
||||||
|
b = row[ix * 2 + 1]
|
||||||
|
c = ((a & 0xf) << 4) | ((b & 0xf) << 0)
|
||||||
|
yield c
|
||||||
|
|
||||||
|
def emit_tiles(tiles):
|
||||||
|
for tile in tiles:
|
||||||
|
yield from emit_tile(tile)
|
||||||
|
|
||||||
|
def emit_tile_data(tiles):
|
||||||
|
b = bytes(emit_tiles(tiles))
|
||||||
|
with open(sys.argv[2], 'wb') as f:
|
||||||
|
f.write(b)
|
||||||
|
|
||||||
|
def emit_pattern_data(pattern):
|
||||||
|
with open(sys.argv[3], 'wb') as f:
|
||||||
|
for ix in pattern:
|
||||||
|
assert ix < 1200, ix
|
||||||
|
b = struct.pack('>H', ix)
|
||||||
|
f.write(b)
|
||||||
|
|
||||||
|
assert len(sys.argv) == 4, len(sys.argv)
|
||||||
|
tiles, pattern = tile_input(buf)
|
||||||
|
emit_tile_data(tiles)
|
||||||
|
emit_pattern_data(pattern)
|
@ -25,26 +25,22 @@ load_bitmap_char(FT_Face face,
|
|||||||
//printf("num_grays %d\n", face->glyph->bitmap.num_grays);
|
//printf("num_grays %d\n", face->glyph->bitmap.num_grays);
|
||||||
//printf("pitch %d\n", face->glyph->bitmap.pitch);
|
//printf("pitch %d\n", face->glyph->bitmap.pitch);
|
||||||
//printf("width %d\n", face->glyph->bitmap.width);
|
//printf("width %d\n", face->glyph->bitmap.width);
|
||||||
assert(face->glyph->bitmap.width == 8);
|
|
||||||
//printf("char_code %lx rows %d\n", char_code, face->glyph->bitmap.rows);
|
//printf("char_code %lx rows %d\n", char_code, face->glyph->bitmap.rows);
|
||||||
assert((face->glyph->bitmap.rows % 8) == 0);
|
//assert((face->glyph->bitmap.rows % 8) == 0);
|
||||||
assert(face->glyph->bitmap.width / face->glyph->bitmap.pitch == 8);
|
//assert(face->glyph->bitmap.width / face->glyph->bitmap.pitch == 8);
|
||||||
|
|
||||||
for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) {
|
for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) {
|
||||||
uint8_t * row = &face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch];
|
uint8_t * row = &face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch];
|
||||||
uint8_t row_out = 0;
|
uint8_t row_out = 0;
|
||||||
for (unsigned int x = 0; x < face->glyph->bitmap.width; x++) {
|
for (unsigned int x = 0; x < face->glyph->bitmap.width; x++) {
|
||||||
int bit;
|
if (x % 8 == 0) row_out = 0;
|
||||||
if (x < face->glyph->bitmap.width) {
|
const uint8_t bit = (row[x / 8] >> (7 - (x % 8))) & 1;
|
||||||
bit = (row[x / 8] >> (7 - (x % 8))) & 1;
|
|
||||||
} else {
|
|
||||||
bit = 0;
|
|
||||||
}
|
|
||||||
//std::cerr << (bit ? "█" : " ");
|
//std::cerr << (bit ? "█" : " ");
|
||||||
row_out |= (bit << (7 - (x % 8)));
|
row_out |= (bit << (7 - (x % 8)));
|
||||||
|
if (x % 8 == 7 || x == (face->glyph->bitmap.width - 1))
|
||||||
|
buf[(y * face->glyph->bitmap.pitch) + (x / 8)] = row_out;
|
||||||
}
|
}
|
||||||
//std::cerr << '\n';
|
//std::cerr << "|\n";
|
||||||
buf[y] = row_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'pitch' is bytes; 'width' is pixels
|
// 'pitch' is bytes; 'width' is pixels
|
||||||
|
@ -141,6 +141,9 @@ void main()
|
|||||||
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
||||||
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
|
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
|
||||||
|
|
||||||
|
// disable all VDP2 backgrounds (e.g: the Sega bios logo)
|
||||||
|
vdp2.reg.BGON = 0;
|
||||||
|
|
||||||
// VDP2 User's Manual:
|
// VDP2 User's Manual:
|
||||||
// "When sprite data is in an RGB format, sprite register 0 is selected"
|
// "When sprite data is in an RGB format, sprite register 0 is selected"
|
||||||
// "When the value of a priority number is 0h, it is read as transparent"
|
// "When the value of a priority number is 0h, it is read as transparent"
|
||||||
@ -190,10 +193,3 @@ void main()
|
|||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
227
vdp1/cube2.cpp
Normal file
227
vdp1/cube2.cpp
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include "vdp2.h"
|
||||||
|
#include "vdp1.h"
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
|
#include "../common/vdp2_func.hpp"
|
||||||
|
|
||||||
|
#include "../math/fp.hpp"
|
||||||
|
#include "../math/vec3.hpp"
|
||||||
|
#include "../math/mat3x3.hpp"
|
||||||
|
|
||||||
|
#include "cos.hpp"
|
||||||
|
|
||||||
|
// |--
|
||||||
|
// |
|
||||||
|
// |
|
||||||
|
|
||||||
|
using vec3 = vec<3, fp16_16>;
|
||||||
|
using mat3x3 = mat<3, 3, fp16_16>;
|
||||||
|
|
||||||
|
static constexpr vec3 vertices[8] = {
|
||||||
|
{-0.5, -0.5, 0.5}, // top left front
|
||||||
|
{ 0.5, -0.5, 0.5}, // top right front
|
||||||
|
{ 0.5, 0.5, 0.5}, // bottom right front
|
||||||
|
{-0.5, 0.5, 0.5}, // bottom left front
|
||||||
|
|
||||||
|
{-0.5, -0.5, -0.5}, // top left back
|
||||||
|
{ 0.5, -0.5, -0.5}, // top right back
|
||||||
|
{ 0.5, 0.5, -0.5}, // bottom right back
|
||||||
|
{-0.5, 0.5, -0.5}, // bottom left back
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr uint32_t faces[6][4] = {
|
||||||
|
{0, 1, 2, 3}, // front clockwise
|
||||||
|
{5, 4, 7, 6}, // back clockwise
|
||||||
|
{0, 4, 5, 1}, // top clockwise
|
||||||
|
{3, 2, 6, 7}, // bottom clockwise
|
||||||
|
{4, 0, 3, 7}, // left clockwise
|
||||||
|
{1, 5, 6, 2}, // right clockwise
|
||||||
|
};
|
||||||
|
|
||||||
|
consteval vec3 normal(int32_t ix)
|
||||||
|
{
|
||||||
|
const uint32_t * face = faces[ix];
|
||||||
|
vec3 a = vertices[face[1]] - vertices[face[0]];
|
||||||
|
vec3 b = vertices[face[3]] - vertices[face[0]];
|
||||||
|
return vertices[face[0]] + cross(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr vec3 normals[6] = {
|
||||||
|
normal(0),
|
||||||
|
normal(1),
|
||||||
|
normal(2),
|
||||||
|
normal(3),
|
||||||
|
normal(4),
|
||||||
|
normal(5),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct canvas {
|
||||||
|
fp16_16 width;
|
||||||
|
fp16_16 height;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr struct canvas canvas = { 240, 240 };
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vec<3, T> viewport_to_canvas(T x, T y)
|
||||||
|
{
|
||||||
|
return vec<3, T>(x * canvas.width, y * canvas.height, T(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr vec<3, T> project_vertex(vec<3, T> const& v)
|
||||||
|
{
|
||||||
|
// / (v.z - T(5))
|
||||||
|
// / (v.z - T(5))
|
||||||
|
return viewport_to_canvas<T>((v.x * T(0.5) + T(2.0/3.0)),
|
||||||
|
(v.y * T(0.5) + T(0.5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline uint16_t rgb15(int32_t r, int32_t g, int32_t b)
|
||||||
|
{
|
||||||
|
return ((b & 31) << 10) | ((g & 31) << 5) | ((r & 31) << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint16_t colors[] = {
|
||||||
|
rgb15(31, 0, 0), // red
|
||||||
|
rgb15( 0, 31, 0), // green
|
||||||
|
rgb15( 0, 0, 31), // blue
|
||||||
|
rgb15(31, 0, 31), // magenta
|
||||||
|
rgb15( 0, 31, 31), // cyan
|
||||||
|
rgb15(31, 31, 0), // yellow
|
||||||
|
};
|
||||||
|
|
||||||
|
static int32_t tick = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
tick++;
|
||||||
|
int ix = 2;
|
||||||
|
|
||||||
|
const int rx = tick >> 2;
|
||||||
|
const mat3x3 rotationX {
|
||||||
|
1, 0, 0,
|
||||||
|
0, cos(rx), sin(rx),
|
||||||
|
0, -sin(rx), cos(rx)
|
||||||
|
};
|
||||||
|
|
||||||
|
const int ry = tick >> 1;
|
||||||
|
const mat3x3 rotationY {
|
||||||
|
cos(ry), 0, -sin(ry),
|
||||||
|
0, 1, 0,
|
||||||
|
sin(ry), 0, cos(ry)
|
||||||
|
};
|
||||||
|
|
||||||
|
const mat3x3 transform = rotationX * rotationY;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
|
||||||
|
const uint32_t * face = faces[i];
|
||||||
|
|
||||||
|
const vec3& origin = transform * vertices[face[0]];
|
||||||
|
const vec3& normal = (transform * normals[i]);
|
||||||
|
const vec3& origin_p = project_vertex(origin);
|
||||||
|
const vec3& normal_p = project_vertex(normal);
|
||||||
|
const vec3 camera = {2.0/3.0, 0.5, 100};
|
||||||
|
fp16_16 cull = dot((origin - camera), normal - origin);
|
||||||
|
|
||||||
|
if ((cull.value >> 16) < 0) {
|
||||||
|
vdp1.vram.cmd[ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__POLYGON;
|
||||||
|
vdp1.vram.cmd[ix].LINK = 0;
|
||||||
|
vdp1.vram.cmd[ix].PMOD = PMOD__ECD | PMOD__SPD;
|
||||||
|
vdp1.vram.cmd[ix].COLR = COLR__RGB | colors[i];
|
||||||
|
|
||||||
|
for (int p = 0; p < 4; p++) {
|
||||||
|
const vec3& v0 = vertices[face[p]];
|
||||||
|
|
||||||
|
const vec3 v1 = transform * v0;
|
||||||
|
|
||||||
|
const vec3& v2 = project_vertex(v1);
|
||||||
|
|
||||||
|
vdp1.vram.cmd[ix].point[p].X = static_cast<int>(v2.x);
|
||||||
|
vdp1.vram.cmd[ix].point[p].Y = static_cast<int>(v2.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
ix++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
vdp1.vram.cmd[ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__LINE;
|
||||||
|
vdp1.vram.cmd[ix].LINK = 0;
|
||||||
|
vdp1.vram.cmd[ix].PMOD = PMOD__ECD | PMOD__SPD;
|
||||||
|
vdp1.vram.cmd[ix].COLR = COLR__RGB | colors[i];
|
||||||
|
vdp1.vram.cmd[ix].point[0].X = static_cast<int>(origin_p.x);
|
||||||
|
vdp1.vram.cmd[ix].point[0].Y = static_cast<int>(origin_p.y);
|
||||||
|
vdp1.vram.cmd[ix].point[1].X = static_cast<int>(normal_p.x);
|
||||||
|
vdp1.vram.cmd[ix].point[1].Y = static_cast<int>(normal_p.y);
|
||||||
|
|
||||||
|
ix++;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vdp1.vram.cmd[ix].CTRL = CTRL__END;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
v_blank_in();
|
||||||
|
|
||||||
|
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
|
||||||
|
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
||||||
|
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
|
||||||
|
|
||||||
|
// disable all VDP2 backgrounds (e.g: the Sega bios logo)
|
||||||
|
vdp2.reg.BGON = 0;
|
||||||
|
|
||||||
|
// VDP2 User's Manual:
|
||||||
|
// "When sprite data is in an RGB format, sprite register 0 is selected"
|
||||||
|
// "When the value of a priority number is 0h, it is read as transparent"
|
||||||
|
//
|
||||||
|
// The power-on value of PRISA is zero. Set the priority for sprite register 0
|
||||||
|
// to some number greater than zero, so that the color data is not interpreted
|
||||||
|
// as "transparent".
|
||||||
|
vdp2.reg.PRISA = PRISA__S0PRIN(1); // Sprite register 0 Priority Number
|
||||||
|
|
||||||
|
/* TVM settings must be performed from the second H-blank IN interrupt after the
|
||||||
|
V-blank IN interrupt to the H-blank IN interrupt immediately after the V-blank
|
||||||
|
OUT interrupt. */
|
||||||
|
// "normal" display resolution, 16 bits per pixel, 512x256 framebuffer
|
||||||
|
vdp1.reg.TVMR = TVMR__TVM__NORMAL;
|
||||||
|
|
||||||
|
// swap framebuffers every 1 cycle; non-interlace
|
||||||
|
vdp1.reg.FBCR = 0;
|
||||||
|
|
||||||
|
// during a framebuffer erase cycle, write the color "black" to each pixel
|
||||||
|
constexpr uint16_t black = 0x0000;
|
||||||
|
vdp1.reg.EWDR = black;
|
||||||
|
|
||||||
|
// the EWLR/EWRR macros use somewhat nontrivial math for the X coordinates
|
||||||
|
// erase upper-left coordinate
|
||||||
|
vdp1.reg.EWLR = EWLR__16BPP_X1(0) | EWLR__Y1(0);
|
||||||
|
|
||||||
|
// erase lower-right coordinate
|
||||||
|
vdp1.reg.EWRR = EWRR__16BPP_X3(319) | EWRR__Y3(239);
|
||||||
|
|
||||||
|
vdp1.vram.cmd[0].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__SYSTEM_CLIP_COORDINATES;
|
||||||
|
vdp1.vram.cmd[0].LINK = 0;
|
||||||
|
vdp1.vram.cmd[0].XC = 319;
|
||||||
|
vdp1.vram.cmd[0].YC = 239;
|
||||||
|
|
||||||
|
vdp1.vram.cmd[1].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__LOCAL_COORDINATE;
|
||||||
|
vdp1.vram.cmd[1].LINK = 0;
|
||||||
|
vdp1.vram.cmd[1].XA = 0;
|
||||||
|
vdp1.vram.cmd[1].YA = 0;
|
||||||
|
|
||||||
|
vdp1.vram.cmd[2].CTRL = CTRL__END;
|
||||||
|
|
||||||
|
// start drawing (execute the command list) on every frame
|
||||||
|
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
v_blank_in();
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
}
|
@ -204,10 +204,3 @@ void main()
|
|||||||
// start drawing (execute the command list) on every frame
|
// start drawing (execute the command list) on every frame
|
||||||
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
@ -150,10 +150,3 @@ void main()
|
|||||||
// start drawing (execute the command list) on every frame
|
// start drawing (execute the command list) on every frame
|
||||||
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
@ -173,7 +173,7 @@ void main()
|
|||||||
// It appears Kronos does not correctly calculate the color address in the
|
// It appears Kronos does not correctly calculate the color address in the
|
||||||
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
||||||
// in this example is 7FFE0.
|
// in this example is 7FFE0.
|
||||||
vdp1.vram.cmd[2].COLR = COLR__ADDRESS(color_address); // non-palettized (rgb15) color data
|
vdp1.vram.cmd[2].COLR = COLR__LOOKUP_TABLE__ADDRESS(color_address); // non-palettized (rgb15) color data
|
||||||
vdp1.vram.cmd[2].SRCA = SRCA(character_address);
|
vdp1.vram.cmd[2].SRCA = SRCA(character_address);
|
||||||
vdp1.vram.cmd[2].SIZE = SIZE__X(sprite_width) | SIZE__Y(sprite_height);
|
vdp1.vram.cmd[2].SIZE = SIZE__X(sprite_width) | SIZE__Y(sprite_height);
|
||||||
vdp1.vram.cmd[2].XA = 100;
|
vdp1.vram.cmd[2].XA = 100;
|
||||||
@ -193,10 +193,3 @@ void main()
|
|||||||
scu.reg.IST = 0;
|
scu.reg.IST = 0;
|
||||||
scu.reg.IMS = ~(IMS__V_BLANK_IN);
|
scu.reg.IMS = ~(IMS__V_BLANK_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
@ -57,7 +57,7 @@ uint32_t character_pattern_table(const uint32_t top)
|
|||||||
// `table_size` is in bytes; divide by two to get uint16_t indicies.
|
// `table_size` is in bytes; divide by two to get uint16_t indicies.
|
||||||
uint32_t buf_ix = 0;
|
uint32_t buf_ix = 0;
|
||||||
for (uint32_t table_ix = 0; table_ix < (table_size / 2); table_ix++) {
|
for (uint32_t table_ix = 0; table_ix < (table_size / 2); table_ix++) {
|
||||||
uint32_t tmp = buf[buf_ix];
|
uint16_t tmp = buf[buf_ix];
|
||||||
|
|
||||||
table[table_ix] = (((tmp >> 8) & 0xff) << 8)
|
table[table_ix] = (((tmp >> 8) & 0xff) << 8)
|
||||||
| (((tmp >> 0) & 0xff) << 0);
|
| (((tmp >> 0) & 0xff) << 0);
|
||||||
@ -72,7 +72,7 @@ void main()
|
|||||||
{
|
{
|
||||||
uint32_t color_address, character_address;
|
uint32_t color_address, character_address;
|
||||||
uint32_t top = (sizeof (union vdp1_vram));
|
uint32_t top = (sizeof (union vdp1_vram));
|
||||||
uint32_t color_bank = 5; // completely random and arbitrary value
|
uint32_t color_bank = 0; // completely random and arbitrary value
|
||||||
color_palette(color_bank);
|
color_palette(color_bank);
|
||||||
// For color bank color, COLR is concatenated bitwise with pixel data. See
|
// For color bank color, COLR is concatenated bitwise with pixel data. See
|
||||||
// Figure 6.17 in the VDP1 manual.
|
// Figure 6.17 in the VDP1 manual.
|
||||||
@ -146,10 +146,3 @@ void main()
|
|||||||
// start drawing (execute the command list) on every frame
|
// start drawing (execute the command list) on every frame
|
||||||
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
@ -73,10 +73,3 @@ void main()
|
|||||||
// start drawing (execute the command list) on every frame
|
// start drawing (execute the command list) on every frame
|
||||||
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
@ -103,10 +103,3 @@ void main()
|
|||||||
// start drawing (execute the command list) on every frame
|
// start drawing (execute the command list) on every frame
|
||||||
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1) {}
|
|
||||||
}
|
|
||||||
|
310
vdp2/color_calculation_ratio.cpp
Normal file
310
vdp2/color_calculation_ratio.cpp
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include "vdp2.h"
|
||||||
|
#include "vdp1.h"
|
||||||
|
|
||||||
|
#include "../common/vdp2_func.hpp"
|
||||||
|
#include "../common/copy.hpp"
|
||||||
|
|
||||||
|
extern void * _mai_data_pal_start __asm("_binary_res_mai_data_pal_start");
|
||||||
|
extern void * _mai_data_pal_size __asm("_binary_res_mai_data_pal_size");
|
||||||
|
|
||||||
|
extern void * _mai00_data_start __asm("_binary_res_mai00_data_start");
|
||||||
|
extern void * _mai00_data_size __asm("_binary_res_mai00_data_size");
|
||||||
|
|
||||||
|
extern void * _haohmaru_data_pal_start __asm("_binary_res_haohmaru_data_pal_start");
|
||||||
|
extern void * _haohmaru_data_pal_size __asm("_binary_res_haohmaru_data_pal_size");
|
||||||
|
|
||||||
|
extern void * _haohmaru_data_start __asm("_binary_res_haohmaru_data_start");
|
||||||
|
extern void * _haohmaru_data_size __asm("_binary_res_haohmaru_data_size");
|
||||||
|
|
||||||
|
extern void * _forest_pattern_start __asm("_binary_res_forest_pattern_start");
|
||||||
|
extern void * _forest_pattern_size __asm("_binary_res_forest_pattern_size");
|
||||||
|
|
||||||
|
extern void * _forest_tile_start __asm("_binary_res_forest_tile_start");
|
||||||
|
extern void * _forest_tile_size __asm("_binary_res_forest_tile_size");
|
||||||
|
|
||||||
|
extern void * _forest_data_pal_start __asm("_binary_res_forest_data_pal_start");
|
||||||
|
extern void * _forest_data_pal_size __asm("_binary_res_forest_data_pal_size");
|
||||||
|
|
||||||
|
inline constexpr uint16_t rgb15(const uint8_t * rgb24)
|
||||||
|
{
|
||||||
|
return ((rgb24[2] >> 3) << 10) // blue
|
||||||
|
| ((rgb24[1] >> 3) << 5) // green
|
||||||
|
| ((rgb24[0] >> 3) << 0); // red
|
||||||
|
}
|
||||||
|
|
||||||
|
void vdp2_color_palette(const uint32_t color_index_offset,
|
||||||
|
const uint8_t * buf,
|
||||||
|
const uint32_t buf_size)
|
||||||
|
{
|
||||||
|
uint16_t * table = &vdp2.cram.u16[color_index_offset];
|
||||||
|
|
||||||
|
uint32_t buf_ix = 0;
|
||||||
|
for (uint32_t i = 0; i < (buf_size / 3); i++) {
|
||||||
|
table[i] = rgb15(&buf[buf_ix]);
|
||||||
|
buf_ix += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vdp2_color_palette()
|
||||||
|
{
|
||||||
|
{ /* mai palette */
|
||||||
|
const uint32_t buf_size = reinterpret_cast<uint32_t>(&_mai_data_pal_size);
|
||||||
|
const uint8_t * buf = reinterpret_cast<uint8_t*>(&_mai_data_pal_start);
|
||||||
|
|
||||||
|
vdp2_color_palette(0, buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* forest palette */
|
||||||
|
const uint32_t buf_size = reinterpret_cast<uint32_t>(&_forest_data_pal_size);
|
||||||
|
const uint8_t * buf = reinterpret_cast<uint8_t*>(&_forest_data_pal_start);
|
||||||
|
|
||||||
|
vdp2_color_palette(16, buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* haohmaru palette */
|
||||||
|
const uint32_t buf_size = reinterpret_cast<uint32_t>(&_haohmaru_data_pal_size);
|
||||||
|
const uint8_t * buf = reinterpret_cast<uint8_t*>(&_haohmaru_data_pal_start);
|
||||||
|
|
||||||
|
vdp2_color_palette(32, buf, buf_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t character_pattern_table(const uint32_t top, const uint32_t * buf, const uint32_t buf_size)
|
||||||
|
{
|
||||||
|
// Unlike vdp2 cell format, vdp1 sprites appear to be much more dimensionally
|
||||||
|
// flexible. The data is interpreted as a row-major packed array, where the
|
||||||
|
// row/horizontal stride is equal to the sprite width (as configured in the
|
||||||
|
// draw command). This is identical to how the input palette index data is
|
||||||
|
// structured, so there is no transformation to do here, only a plain memory
|
||||||
|
// copy.
|
||||||
|
|
||||||
|
// Divide `buf_size` by two because this converts (indexed color) 8 bit pixels
|
||||||
|
// to 4 bit pixels. Round up to the nearest 0x20 (for an 8000 pixel/8000 byte
|
||||||
|
// image, this rounding is a no-op).
|
||||||
|
const uint32_t table_size = ((buf_size / 2) + 0x20 - 1) & (-0x20);
|
||||||
|
const uint32_t table_address = top - table_size;
|
||||||
|
uint16_t * table = &vdp1.vram.u16[(table_address / 2)];
|
||||||
|
|
||||||
|
// `table_size` is in bytes; divide by two to get uint16_t indicies.
|
||||||
|
uint32_t buf_ix = 0;
|
||||||
|
for (uint32_t table_ix = 0; table_ix < (table_size / 2); table_ix++) {
|
||||||
|
uint32_t tmp = buf[buf_ix];
|
||||||
|
|
||||||
|
table[table_ix] = (((tmp >> 24) & 0xf) << 12)
|
||||||
|
| (((tmp >> 16) & 0xf) << 8 )
|
||||||
|
| (((tmp >> 8 ) & 0xf) << 4 )
|
||||||
|
| (((tmp >> 0 ) & 0xf) << 0 );
|
||||||
|
|
||||||
|
buf_ix += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return table_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t forest_cell_data(uint32_t top)
|
||||||
|
{
|
||||||
|
const uint32_t buf_size = reinterpret_cast<uint32_t>(&_forest_tile_size);
|
||||||
|
const uint32_t * buf = reinterpret_cast<uint32_t*>(&_forest_tile_start);
|
||||||
|
|
||||||
|
// round to nearest multiple of 32
|
||||||
|
const uint32_t table_size = ((buf_size) + 0x20 - 1) & (-0x20);
|
||||||
|
const uint32_t base_address = top - table_size; // in bytes
|
||||||
|
|
||||||
|
copy<uint32_t>(&vdp2.vram.u32[base_address / 4], buf, buf_size);
|
||||||
|
|
||||||
|
return base_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void forest_init()
|
||||||
|
{
|
||||||
|
/* enable display of NBG0 */
|
||||||
|
vdp2.reg.BGON = BGON__N0ON | BGON__N0TPON;
|
||||||
|
|
||||||
|
/* set character format for NBG0 to palettized 16 color
|
||||||
|
set enable "cell format" for NBG0
|
||||||
|
set character size for NBG0 to 1x1 cell */
|
||||||
|
vdp2.reg.CHCTLA = CHCTLA__N0CHCN__16_COLOR
|
||||||
|
| CHCTLA__N0BMEN__CELL_FORMAT
|
||||||
|
| CHCTLA__N0CHSZ__1x1_CELL;
|
||||||
|
|
||||||
|
/* plane size */
|
||||||
|
vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1;
|
||||||
|
|
||||||
|
/* map plane offset
|
||||||
|
1-word: value of bit 6-0 * 0x2000
|
||||||
|
2-word: value of bit 5-0 * 0x4000
|
||||||
|
*/
|
||||||
|
constexpr int plane_a = 0;
|
||||||
|
constexpr int plane_a_offset = plane_a * 0x4000;
|
||||||
|
|
||||||
|
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
||||||
|
vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0
|
||||||
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0
|
||||||
|
|
||||||
|
uint32_t top = (sizeof (union vdp2_vram));
|
||||||
|
|
||||||
|
uint32_t cell_top = top = forest_cell_data(0x080000);
|
||||||
|
uint32_t pattern_name = cell_top / 32;
|
||||||
|
|
||||||
|
/* use 2-word (32-bit) pattern names */
|
||||||
|
vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD;
|
||||||
|
|
||||||
|
const uint32_t buf_size = reinterpret_cast<uint32_t>(&_forest_pattern_size);
|
||||||
|
const uint16_t * buf = reinterpret_cast<uint16_t*>(&_forest_pattern_start);
|
||||||
|
|
||||||
|
uint32_t * pattern = &vdp2.vram.u32[(plane_a_offset / 4)];
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
for (uint32_t i = 0; i < (buf_size / 2); i++) {
|
||||||
|
pattern[y * 64 + x] = 1 << 16 | (buf[i] + (cell_top / 32));
|
||||||
|
x++;
|
||||||
|
if (x >= 40) {
|
||||||
|
x = 0;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vdp2.reg.VRSIZE = 0;
|
||||||
|
vdp2.reg.RAMCTL = 0;
|
||||||
|
|
||||||
|
vdp2.reg.CYCA0 = 0xeeee'eeee;
|
||||||
|
vdp2.reg.CYCA1 = 0xeeee'eeee;
|
||||||
|
vdp2.reg.CYCB0 = 0xeeee'eeee;
|
||||||
|
vdp2.reg.CYCB1 = 0xeeee'eeee;
|
||||||
|
|
||||||
|
vdp2.reg.VRSIZE = 0;
|
||||||
|
|
||||||
|
vdp2_color_palette();
|
||||||
|
forest_init();
|
||||||
|
|
||||||
|
vdp2.reg.RAMCTL = RAMCTL__VRAMD | RAMCTL__VRBMD;
|
||||||
|
|
||||||
|
vdp2.reg.CYCA0 = 0x0fff'ffff;
|
||||||
|
vdp2.reg.CYCA1 = 0xffff'ffff;
|
||||||
|
vdp2.reg.CYCB0 = 0xffff'ffff;
|
||||||
|
vdp2.reg.CYCB1 = 0x4fff'ffff;
|
||||||
|
|
||||||
|
uint32_t mai_character_address;
|
||||||
|
uint32_t haohmaru_character_address;
|
||||||
|
uint32_t top = (sizeof (union vdp1_vram));
|
||||||
|
|
||||||
|
{ /* mai */
|
||||||
|
const uint32_t buf_size = reinterpret_cast<uint32_t>(&_mai00_data_size);
|
||||||
|
const uint32_t * buf = reinterpret_cast<uint32_t*>(&_mai00_data_start);
|
||||||
|
top = mai_character_address = character_pattern_table(top, buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /* haohmaru */
|
||||||
|
const uint32_t buf_size = reinterpret_cast<uint32_t>(&_haohmaru_data_size);
|
||||||
|
const uint32_t * buf = reinterpret_cast<uint32_t*>(&_haohmaru_data_start);
|
||||||
|
top = haohmaru_character_address = character_pattern_table(top, buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
|
||||||
|
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
|
||||||
|
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
|
||||||
|
|
||||||
|
// VDP2 User's Manual:
|
||||||
|
// "When sprite data is in an RGB format, sprite register 0 is selected"
|
||||||
|
// "When the value of a priority number is 0h, it is read as transparent"
|
||||||
|
//
|
||||||
|
// From a VDP2 perspective: in VDP1 16-color lookup table mode, VDP1 is still
|
||||||
|
// sending RGB data to VDP2. This sprite color data as configured in
|
||||||
|
// `color_lookup_table` from a VDP2 priority perspective uses sprite register 0.
|
||||||
|
//
|
||||||
|
// The power-on value of PRISA is zero. Set the priority for sprite register 0
|
||||||
|
// to some number greater than zero, so that the color data is not interpreted
|
||||||
|
// as "transparent".
|
||||||
|
vdp2.reg.PRISA = PRISA__S0PRIN(2) // Sprite register 0 PRIority Number
|
||||||
|
| PRISA__S1PRIN(1);
|
||||||
|
vdp2.reg.PRINA = PRINA__N0PRIN(1);
|
||||||
|
|
||||||
|
/* TVM settings must be performed from the second H-blank IN interrupt after the
|
||||||
|
V-blank IN interrupt to the H-blank IN interrupt immediately after the V-blank
|
||||||
|
OUT interrupt. */
|
||||||
|
// "normal" display resolution, 16 bits per pixel, 512x256 framebuffer
|
||||||
|
vdp1.reg.TVMR = TVMR__TVM__NORMAL;
|
||||||
|
|
||||||
|
// swap framebuffers every 1 cycle; non-interlace
|
||||||
|
vdp1.reg.FBCR = 0;
|
||||||
|
|
||||||
|
// during a framebuffer erase cycle, write the color "black" to each pixel
|
||||||
|
constexpr uint16_t black = 0x0000;
|
||||||
|
vdp1.reg.EWDR = black;
|
||||||
|
|
||||||
|
// the EWLR/EWRR macros use somewhat nontrivial math for the X coordinates
|
||||||
|
// erase upper-left coordinate
|
||||||
|
vdp1.reg.EWLR = EWLR__16BPP_X1(0) | EWLR__Y1(0);
|
||||||
|
|
||||||
|
// erase lower-right coordinate
|
||||||
|
vdp1.reg.EWRR = EWRR__16BPP_X3(319) | EWRR__Y3(239);
|
||||||
|
|
||||||
|
vdp1.vram.cmd[0].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__SYSTEM_CLIP_COORDINATES;
|
||||||
|
vdp1.vram.cmd[0].LINK = 0;
|
||||||
|
vdp1.vram.cmd[0].XC = 319;
|
||||||
|
vdp1.vram.cmd[0].YC = 239;
|
||||||
|
|
||||||
|
vdp1.vram.cmd[1].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__LOCAL_COORDINATE;
|
||||||
|
vdp1.vram.cmd[1].LINK = 0;
|
||||||
|
vdp1.vram.cmd[1].XA = 0;
|
||||||
|
vdp1.vram.cmd[1].YA = 0;
|
||||||
|
|
||||||
|
vdp1.vram.cmd[2].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE;
|
||||||
|
vdp1.vram.cmd[2].LINK = 0;
|
||||||
|
// The "end code" is 0xf, which is being used in the mai sprite palette. If
|
||||||
|
// both transparency and end codes are enabled, it seems there are only 14
|
||||||
|
// usable colors in the 4-bit color mode.
|
||||||
|
vdp1.vram.cmd[2].PMOD = PMOD__ECD | PMOD__COLOR_MODE__COLOR_BANK_16;
|
||||||
|
// It appears Kronos does not correctly calculate the color address in the
|
||||||
|
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
||||||
|
// in this example is 7FFE0.
|
||||||
|
vdp1.vram.cmd[2].COLR = 0;
|
||||||
|
vdp1.vram.cmd[2].SRCA = mai_character_address >> 3;
|
||||||
|
vdp1.vram.cmd[2].SIZE = SIZE__X(72) | SIZE__Y(100);
|
||||||
|
vdp1.vram.cmd[2].XA = 100;
|
||||||
|
vdp1.vram.cmd[2].YA = 100;
|
||||||
|
|
||||||
|
vdp1.vram.cmd[3].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE;
|
||||||
|
vdp1.vram.cmd[3].LINK = 0;
|
||||||
|
// The "end code" is 0xf, which is being used in the mai sprite palette. If
|
||||||
|
// both transparency and end codes are enabled, it seems there are only 14
|
||||||
|
// usable colors in the 4-bit color mode.
|
||||||
|
vdp1.vram.cmd[3].PMOD = PMOD__ECD | PMOD__COLOR_MODE__COLOR_BANK_16;
|
||||||
|
// It appears Kronos does not correctly calculate the color address in the
|
||||||
|
// VDP1 debugger. Kronos will report FFFC when the actual color table address
|
||||||
|
// in this example is 7FFE0.
|
||||||
|
vdp1.vram.cmd[3].COLR = (0b01 << 14) | 32;
|
||||||
|
vdp1.vram.cmd[3].SRCA = haohmaru_character_address >> 3;
|
||||||
|
vdp1.vram.cmd[3].SIZE = SIZE__X(104) | SIZE__Y(132);
|
||||||
|
vdp1.vram.cmd[3].XA = 120;
|
||||||
|
vdp1.vram.cmd[3].YA = 110;
|
||||||
|
|
||||||
|
vdp1.vram.cmd[4].CTRL = CTRL__END;
|
||||||
|
|
||||||
|
// start drawing (execute the command list) on every frame
|
||||||
|
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
|
||||||
|
|
||||||
|
vdp2.reg.SPCTL = SPCTL__SPCCCS__EQUAL
|
||||||
|
| SPCTL__SPCCN(1)
|
||||||
|
| SPCTL__SPTYPE(0);
|
||||||
|
|
||||||
|
vdp2.reg.CCCTL = CCCTL__SPCCEN;
|
||||||
|
|
||||||
|
int dir = 1;
|
||||||
|
int ratio = 0;
|
||||||
|
while (1) {
|
||||||
|
v_blank_in();
|
||||||
|
|
||||||
|
vdp2.reg.CCRSA = CCRSA__S0CCRT(ratio >> 2);
|
||||||
|
|
||||||
|
ratio += dir;
|
||||||
|
if (ratio >= (32 * 4) || ratio < 0) {
|
||||||
|
dir = -dir;
|
||||||
|
ratio += dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "vdp2.h"
|
#include "vdp2.h"
|
||||||
#include "../common/vdp2_func.h"
|
#include "../common/vdp2_func.hpp"
|
||||||
|
|
||||||
extern void * _butterfly_data_pal_start __asm("_binary_res_butterfly_data_pal_start");
|
extern void * _butterfly_data_pal_start __asm("_binary_res_butterfly_data_pal_start");
|
||||||
extern void * _butterfly_data_pal_size __asm("_binary_res_butterfly_data_pal_size");
|
extern void * _butterfly_data_pal_size __asm("_binary_res_butterfly_data_pal_size");
|
||||||
@ -107,8 +107,8 @@ void main()
|
|||||||
constexpr int plane_size = page_size * 1;
|
constexpr int plane_size = page_size * 1;
|
||||||
|
|
||||||
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
||||||
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0
|
vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0
|
||||||
vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0
|
||||||
|
|
||||||
constexpr int cell_size = (8 * 8) * 2; // N0CHCN__2048_COLOR (16-bit)
|
constexpr int cell_size = (8 * 8) * 2; // N0CHCN__2048_COLOR (16-bit)
|
||||||
constexpr int character_size = cell_size * (1 * 1); // N0CHSZ__1x1_CELL
|
constexpr int character_size = cell_size * (1 * 1); // N0CHSZ__1x1_CELL
|
||||||
|
@ -105,7 +105,7 @@ void main()
|
|||||||
|
|
||||||
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
|
||||||
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0
|
vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0
|
||||||
vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0
|
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(0) | MPCDN0__N0MPC(0); // bits 5~0
|
||||||
|
|
||||||
uint32_t top = (sizeof (union vdp2_vram));
|
uint32_t top = (sizeof (union vdp2_vram));
|
||||||
palette_data();
|
palette_data();
|
||||||
@ -118,7 +118,7 @@ void main()
|
|||||||
|
|
||||||
/* use 2-word (32-bit) pattern names */
|
/* use 2-word (32-bit) pattern names */
|
||||||
vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD;
|
vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD;
|
||||||
fill<uint32_t>(&vdp2.vram.u32[(plane_a_offset / 2)], pattern_name, plane_size);
|
fill<uint32_t>(&vdp2.vram.u32[(plane_a_offset / 4)], pattern_name, plane_size);
|
||||||
|
|
||||||
// both 1-word and 2-word have identical behavior; 2-word is enabled to reduce/focus suspicion.
|
// both 1-word and 2-word have identical behavior; 2-word is enabled to reduce/focus suspicion.
|
||||||
}
|
}
|
||||||
|
@ -248,10 +248,3 @@ void main()
|
|||||||
scu.reg.IST = 0;
|
scu.reg.IST = 0;
|
||||||
scu.reg.IMS = ~(IMS__SMPC | IMS__V_BLANK_IN);
|
scu.reg.IMS = ~(IMS__SMPC | IMS__V_BLANK_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
|
||||||
void start(void)
|
|
||||||
{
|
|
||||||
main();
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user