diff options
author | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
---|---|---|
committer | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
commit | abef6da56913f1c55528103e60a50451a39628b1 (patch) | |
tree | b3c8092471ecbb73e568cd0d336efa0e7871ee8d /misc/dreamcast |
initial commit
Diffstat (limited to 'misc/dreamcast')
-rw-r--r-- | misc/dreamcast/DrawColouredQuads.S | 65 | ||||
-rw-r--r-- | misc/dreamcast/DrawTexturedQuads.S | 63 | ||||
-rw-r--r-- | misc/dreamcast/Makefile | 66 | ||||
-rw-r--r-- | misc/dreamcast/ViewportTransform.S | 218 | ||||
-rw-r--r-- | misc/dreamcast/boot_logo.png | bin | 0 -> 4021 bytes | |||
-rw-r--r-- | misc/dreamcast/ip.txt | 3 | ||||
-rw-r--r-- | misc/dreamcast/readme.txt | 9 |
7 files changed, 424 insertions, 0 deletions
diff --git a/misc/dreamcast/DrawColouredQuads.S b/misc/dreamcast/DrawColouredQuads.S new file mode 100644 index 0000000..074605a --- /dev/null +++ b/misc/dreamcast/DrawColouredQuads.S @@ -0,0 +1,65 @@ +#include "ViewportTransform.S" +.global _DrawColouredQuads +.align 4 +.type _DrawColouredQuads,%function + +_DrawColouredQuads: +! Setup + fldi0 fr1 ! U = 0 + fldi0 fr2 ! V = 0 + mov r4,r3 ! r3 = src + add #-32, r5 ! r5 -= sizeof(VERTEX) + ViewportTransformSetup _VP_COL_HWIDTH + +.TRANSFORM_QUAD: + mov.l CMD_COL_VERT, r1 ! r1 = GPU VERT command + + LoadColouredVertex + ProcessVertex1 + + LoadColouredVertex + ProcessVertex2 + + LoadColouredVertex + ProcessVertex3 + + LoadColouredVertex + ProcessVertex4 CMD_COL_EOS + +! CLIPFLAGS TESTING + cmp/eq #0,r0 ! T = r0 == 0 (all points invisible) + bt/s .NO_POINTS_VISIBLE ! if T goto NO_POINTS_VISIBLE + nop + bra .SOME_POINTS_VISIBLE + nop + +.NO_POINTS_VISIBLE: + bra .LOOP_END ! jump to loop end after executing instruction in delay slot + add #-128, r5 ! r5 -= 4 * sizeof(VERTEX), move back to 1 vertex before start of quad + +.SOME_POINTS_VISIBLE: + +.LOOP_END: + dt r6 ! r6--; T = r6 == 0 + bf .TRANSFORM_QUAD ! if !T then goto TRANSFORM_QUAD + nop + + add #32, r5 ! r5 += sizeof(VERTEX) + rts ! return after executing instruction in delay slot + mov r5,r0 ! r0 = r5 + +.align 2 +CMD_COL_VERT: .long 0xe0000000 +CMD_COL_EOS: .long 0xf0000000 + +.global _VP_COL_HWIDTH +_VP_COL_HWIDTH: .long 0 + +.global _VP_COL_HHEIGHT +_VP_COL_HHEIGHT: .long 0 + +.global _VP_COL_X_PLUS_HWIDTH +_VP_COL_X_PLUS_HWIDTH: .long 0 + +.global _VP_COL_Y_PLUS_HHEIGHT +_VP_COL_Y_PLUS_HHEIGHT: .long 0 diff --git a/misc/dreamcast/DrawTexturedQuads.S b/misc/dreamcast/DrawTexturedQuads.S new file mode 100644 index 0000000..5ce16bd --- /dev/null +++ b/misc/dreamcast/DrawTexturedQuads.S @@ -0,0 +1,63 @@ +#include "ViewportTransform.S" +.global _DrawTexturedQuads +.align 4 +.type _DrawTexturedQuads,%function + +_DrawTexturedQuads: +! Setup + mov r4,r3 ! r3 = src + add #-32, r5 ! r5 -= sizeof(VERTEX) + ViewportTransformSetup _VP_TEX_HWIDTH + +.TRANSFORM_QUAD: + mov.l CMD_TEX_VERT, r1 ! r1 = GPU VERT command + + LoadTexturedVertex + ProcessVertex1 + + LoadTexturedVertex + ProcessVertex2 + + LoadTexturedVertex + ProcessVertex3 + + LoadTexturedVertex + ProcessVertex4 CMD_TEX_EOS + +! CLIPFLAGS TESTING + cmp/eq #0,r0 ! T = r0 == 0 (all points invisible) + bt/s .NO_POINTS_VISIBLE ! if T goto NO_POINTS_VISIBLE + nop + bra .SOME_POINTS_VISIBLE + nop + +.NO_POINTS_VISIBLE: + bra .LOOP_END ! jump to loop end after executing instruction in delay slot + add #-128, r5 ! r5 -= 4 * sizeof(VERTEX), move back to prior quad, so that this invisible quad gets overwritten in next iteration + +.SOME_POINTS_VISIBLE: + +.LOOP_END: + dt r6 ! r6--; T = r6 == 0 + bf .TRANSFORM_QUAD ! if !T then goto TRANSFORM_QUAD + nop + + add #32, r5 ! r5 += sizeof(VERTEX) + rts ! return after executing instruction in delay slot + mov r5,r0 ! r0 = r5 + +.align 2 +CMD_TEX_VERT: .long 0xe0000000 +CMD_TEX_EOS: .long 0xf0000000 + +.global _VP_TEX_HWIDTH +_VP_TEX_HWIDTH: .long 0 + +.global _VP_TEX_HHEIGHT +_VP_TEX_HHEIGHT: .long 0 + +.global _VP_TEX_X_PLUS_HWIDTH +_VP_TEX_X_PLUS_HWIDTH: .long 0 + +.global _VP_TEX_Y_PLUS_HHEIGHT +_VP_TEX_Y_PLUS_HHEIGHT: .long 0 diff --git a/misc/dreamcast/Makefile b/misc/dreamcast/Makefile new file mode 100644 index 0000000..5362a41 --- /dev/null +++ b/misc/dreamcast/Makefile @@ -0,0 +1,66 @@ +BUILD_DIR := build-dc +SOURCE_DIRS := src third_party/bearssl/src misc/dreamcast + +S_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.S)) +C_FILES := $(foreach dir,$(SOURCE_DIRS),$(wildcard $(dir)/*.c)) +OBJS := $(addprefix $(BUILD_DIR)/, $(notdir $(C_FILES:%.c=%.o) $(S_FILES:%.S=%.o))) +CFLAGS :=-g -O1 -pipe -fno-math-errno -Ithird_party/bearssl/inc + +GLDC_LIB=third_party/gldc/libGLdc.a +LDFLAGS=-g +LIBS=-lm $(GLDC_LIB) -lppp -lkosfat + +TARGET := ClassiCube-dc +CC_TEXTURES = misc/dreamcast/classicube.zip + +ifeq ($(strip $(KOS_BASE)),) +$(error "Please set KOS variables in your environment.") +endif + +default: $(CC_TEXTURES) $(GLDC_LIB) $(BUILD_DIR) $(TARGET).cdi + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +$(GLDC_LIB): FORCE + $(MAKE) -C third_party/gldc +FORCE: ; + +# TODO add textures to misc folder ? +$(CC_TEXTURES): + curl http://www.classicube.net/static/default.zip -o $@ + +$(BUILD_DIR)/%.o: src/%.c + kos-cc $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: misc/dreamcast/%.S + kos-cc -c $< -o $@ + +$(BUILD_DIR)/%.o: third_party/bearssl/src/%.c + kos-cc $(CFLAGS) -c $< -o $@ + + +$(TARGET).elf: $(OBJS) + kos-cc $(LDFLAGS) $^ -o $@ $(LIBS) + +$(TARGET).bin: $(TARGET).elf + sh-elf-objcopy -R .stack -O binary $(TARGET).elf $(TARGET).bin + +# https://dcemulation.org/phpBB/viewtopic.php?t=105269 +$(TARGET)-scr.bin: $(TARGET).bin + $(KOS_BASE)/utils/scramble/scramble $(TARGET).bin $(TARGET)-scr.bin + +$(TARGET).iso: $(TARGET)-scr.bin + mkdir -p ISO_FILES + cp $(TARGET)-scr.bin ISO_FILES/1ST_READ.BIN + mkdir -p ISO_FILES/audio + mkdir -p ISO_FILES/maps + mkdir -p ISO_FILES/texpacks + mkdir -p ISO_FILES/texturecache + cp $(CC_TEXTURES) ISO_FILES/texpacks/default.zip + cp misc/dreamcast/IP.BIN IP.BIN + mkisofs -G IP.BIN -C 0,11702 -J -l -r -o $(TARGET).iso ISO_FILES + # genisoimage -V ClassiCube -G IP.BIN -joliet -rock -l -o $(TARGET).iso ISO_FILES + +$(TARGET).cdi: $(TARGET).iso + cdi4dc $(TARGET).iso $(TARGET).cdi diff --git a/misc/dreamcast/ViewportTransform.S b/misc/dreamcast/ViewportTransform.S new file mode 100644 index 0000000..19d3052 --- /dev/null +++ b/misc/dreamcast/ViewportTransform.S @@ -0,0 +1,218 @@ +! ========================================================= +! ======================== PROCESSOR INFO ================= +! ========================================================= +! The SH4 can dual issue (i.e. parallel execution) two instructions +! as long as the groups of the two instructions are different: +! * LS - most APU and FPU register load/stores +! * EX - most APU arithmetic instructions +! * MT - TST, CMP, NOP, MOV Rm,Rn +! * FE - most FPU arithmetic instructions +! * CO - other instructions (NOTE: Cannot be exeucted in parallel) + +! Thee following general aspects of instructions are important to note per the SH4 manual: +! * Issue rate: Interval between the issue of an instruction and that of the next instruction +! * Latency: Interval between the issue of an instruction and the generation of its result (completion) +! * Latency is also the interval between the execution of two instructions with an interdependent relationship. +! (although different cases may either increase or decrease Latency) +! + + +! ========================================================= +! ======================== REGISTER USAGES ================ +! ========================================================= +! SH4 C ABI: +! - R0 to R3 are return values (can be overwritten) +! - R4 to R7 are input arguments (can be overwritten) +! - R8 to R13 are non-volatile (must be restored at end) +! - R14 is the frame pointer (must be restored at end) +! - R15 is the stack pointer (must be restored at end) +! - FR0 to FR3 are return values (can be overwritten) +! - FR4 to FR11 are input arguments (can be overwritten) +! - FR12 to FR13 are non-volatile (must be restored at end) + +!r0 = clip flags +!r1 = GPU command +!r2 = temp +!r3 = prefetch address +!r4 = src pointer ARG +!r5 = dst pointer ARG +!r6 = quads count ARG +!r7 = ? + +!fr0 = temp +!fr1 = u +!fr2 = v +!fr3 = c +!fr4 = x +!fr5 = y +!fr6 = z +!fr7 = w +!fr8 = VIEWPORT_HWIDTH +!fr9 = VIEWPORT_HHEIGHT +!fr10 = VIEWPORT_X_PLUS_HWIDTH +!fr11 = VIEWPORT_Y_PLUS_HHEIGHT + +!fv4 = XYZW + + +! ========================================================= +! ========================= VERTEX LOADING ================ +! ========================================================= +.macro LoadColouredVertex +! LOAD XYZ + fmov @r4+, fr4 ! LS, X = src->x + fmov @r4+, fr5 ! LS, Y = src->y + fmov @r4+, fr6 ! LS, Z = src->z + fldi1 fr7 ! LS, W = 1.0 +! PREPARE NEXT VERTEX + add #16, r3 ! EX, r3 += VERTEX_STRIDE + pref @r3 ! LS, PREFETCH r3 (next vertex) + add #64, r5 ! EX, r5 += 2 * sizeof(VERTEX) +! TRANSFORM VERTEX + ftrv xmtrx, fv4 ! FE, TRANSFORM(XYZW) +! LOAD ATTRIBUTES + fmov @r4+,fr3 ! LS, C = src->color +.endm + +.macro LoadTexturedVertex +! LOAD XYZ + fmov @r4+, fr4 ! LS, X = src->x + fmov @r4+, fr5 ! LS, Y = src->y + fmov @r4+, fr6 ! LS, Z = src->z + fldi1 fr7 ! LS, W = 1.0 +! PREPARE NEXT VERTEX + add #24, r3 ! EX, r3 += VERTEX_STRIDE + pref @r3 ! LS, PREFETCH r3 (next vertex) + add #64, r5 ! EX, r5 += 2 * sizeof(VERTEX) +! TRANSFORM VERTEX + ftrv xmtrx, fv4 ! FE, TRANSFORM(XYZW) +! LOAD ATTRIBUTES + fmov @r4+,fr3 ! LS, C = src->color + fmov @r4+,fr1 ! LS, U = src->u + fmov @r4+,fr2 ! LS, V = src->v +.endm + +! ========================================================= +! ========================= VERTEX OUTPUT ================= +! ========================================================= +! To take advantage of SH4 dual instruction processing, +! clipflag calculation and vertex output are interleaved +.macro ProcessVertex1 + fmov.s fr7,@-r5 ! LS, dst->w = W + fmov.s fr3,@-r5 ! LS, dst->c = C + fneg fr7 ! LS, W = -W + fmov.s fr2,@-r5 ! LS, dst->v = V + fcmp/gt fr7,fr6 ! FE, T = Z > W (i.e. Z > -W) + fmov.s fr1,@-r5 ! LS, dst->u = U + movt r0 ! EX, CLIPFLAGS = T + fmov.s fr6,@-r5 ! LS, dst->z = Z + fmov.s fr5,@-r5 ! LS, dst->y = Y + fmov.s fr4,@-r5 ! LS, dst->x = X + mov.l r1,@-r5 ! LS, dst->flags = CMD_VERT +.endm + +.macro ProcessVertex2 + fmov.s fr7,@-r5 ! LS, dst->w = W + fmov.s fr3,@-r5 ! LS, dst->c = C + fneg fr7 ! LS, W = -W + fmov.s fr2,@-r5 ! LS, dst->v = V + fcmp/gt fr7,fr6 ! FE, T = Z > W (i.e. Z > -W) + fmov.s fr1,@-r5 ! LS, dst->u = U + movt r2 ! EX, tmp = T + fmov.s fr6,@-r5 ! LS, dst->z = Z + add r2,r2 ! EX, tmp = tmp + tmp + fmov.s fr5,@-r5 ! LS, dst->y = Y + or r2,r0 ! EX, CLIPFLAGS |= tmp (T << 1) + fmov.s fr4,@-r5 ! LS, dst->x = X + mov.l r1,@-r5 ! LS, dst->flags = CMD_VERT +.endm + +.macro ProcessVertex3 + fmov.s fr7,@-r5 ! LS, dst->w = W + fmov.s fr3,@-r5 ! LS, dst->c = C + fneg fr7 ! LS, W = -W + fmov.s fr2,@-r5 ! LS, dst->v = V + fcmp/gt fr7,fr6 ! FE, T = Z > W (i.e. Z > -W) + fmov.s fr1,@-r5 ! LS, dst->u = U + movt r2 ! EX, tmp = T + fmov.s fr6,@-r5 ! LS, dst->z = Z + fmov.s fr5,@-r5 ! LS, dst->y = Y + shll2 r2 ! EX, tmp = tmp << 2 + fmov.s fr4,@-r5 ! LS, dst->x = X + or r2,r0 ! EX, CLIPFLAGS |= tmp (T << 2) + mov.l r1,@-r5 ! LS, dst->flags = CMD_VERT +.endm + +.macro ProcessVertex4 eos_addr + fmov.s fr7,@-r5 ! LS, dst->w = W + fmov.s fr3,@-r5 ! LS, dst->c = C + fneg fr7 ! LS, W = -W + fmov.s fr2,@-r5 ! LS, dst->v = V + fcmp/gt fr7,fr6 ! FE, T = Z > W (i.e. Z > -W) + fmov.s fr1,@-r5 ! LS, dst->u = U + movt r2 ! EX, tmp = T + fmov.s fr6,@-r5 ! LS, dst->z = Z + shll2 r2 ! EX, tmp = tmp << 2 + fmov.s fr5,@-r5 ! LS, dst->y = Y + add r2,r2 ! EX, tmp = (tmp << 2) + (tmp << 2) + fmov.s fr4,@-r5 ! LS, dst->x = X + mov.l \eos_addr, r1 ! LS, r1 = GPU EOS command + or r2,r0 ! EX, CLIPFLAGS |= tmp (T << 3) + or r0,r1 ! EX, r1 |= CLIPFLAGS + mov.l r1,@-r5 ! LS, dst->flags = GPU EOS | CLIPFLAGS +.endm + + +! ========================================================= +! ====================== VIEWPORT TRANSFORM =============== +! ========================================================= +!r2 = return addr +!r0 = temp +!r5 = dst pointer + +!fr0 = temp +!fr4 = temp +!fr5 = temp +!fr5 = temp +!fr8 = VIEWPORT_HWIDTH +!fr9 = VIEWPORT_HHEIGHT +!fr10 = VIEWPORT_X_PLUS_HWIDTH +!fr11 = VIEWPORT_Y_PLUS_HHEIGHT + +.macro ViewportTransformSetup vp_addr + mova \vp_addr, r0 ! EX, r0 = &VIEWPORT + fmov.s @r0+,fr8 ! LS, fr8 = VIEWPORT_HWIDTH + fmov.s @r0+,fr9 ! LS, fr9 = VIEWPORT_HHEIGHT + fmov.s @r0+,fr10 ! LS, fr10 = VIEWPORT_X_PLUS_HWIDTH + fmov.s @r0+,fr11 ! LS, fr11 = VIEWPORT_Y_PLUS_HHEIGHT + nop ! MT (align to even instructions boundary) +.endm + +.macro ViewportTransformVertex +! INVERSE W CALCULATION + add #28, r5 ! EX, r5 = &vertex->w + fmov.s @r5,fr0 ! LS, fr0 = vertex->w + fmul fr0,fr0 ! FE, fr0 = fr0 * fr0 + add #-24, r5 ! EX, r5 = &vertex->x + fsrra fr0 ! FE, fr0 = 1 / sqrt(fr0) -> 1 / vertex->w + +! TRANSFORM X + fmov.s @r5,fr4 ! LS, fr4 = vertex->x + fmov fr10,fr5 ! LS, fr5 = VIEWPORT_X_PLUS_HWIDTH + fmul fr8,fr4 ! FE, fr4 = VIEWPORT_HWIDTH * vertex->x + fmac fr0,fr4,fr5 ! FE, fr5 = fr0 * fr4 + fr5 -- (X * F * hwidth) + x_plus_hwidth + fmov.s fr5,@r5 ! LS, vertex->x = fr5 + add #4, r5 ! EX, r5 = &vertex->y + +! TRANSFORM Y + fmov.s @r5,fr4 ! LS, fr4 = vertex->y + fmov fr11,fr5 ! LS, fr5 = VIEWPORT_Y_PLUS_HHEIGHT + fmul fr9,fr4 ! FE, fr4 = VIEWPORT_HHEIGHT * vertex->y + fmac fr0,fr4,fr5 ! FE, fr5 = fr0 * fr4 + fr5 -- (Y * F * hheight) + y_plus_hheight + fmov.s fr5,@r5 ! LS, vertex->y = fr5 + add #4, r5 ! EX, r5 = &vertex->z + +! ASSIGN Z + fmov.s fr0,@r5 ! LS, vertex->z = fr0 + add #20, r5 ! EX, r5 += 20 (points to start of next vertex) +.endm diff --git a/misc/dreamcast/boot_logo.png b/misc/dreamcast/boot_logo.png new file mode 100644 index 0000000..eb243c8 --- /dev/null +++ b/misc/dreamcast/boot_logo.png Binary files differdiff --git a/misc/dreamcast/ip.txt b/misc/dreamcast/ip.txt new file mode 100644 index 0000000..e69910a --- /dev/null +++ b/misc/dreamcast/ip.txt @@ -0,0 +1,3 @@ +Version : V1.360 +SW Maker Name : UnknownShadow200 +Game Title : ClassiCube Dreamcast \ No newline at end of file diff --git a/misc/dreamcast/readme.txt b/misc/dreamcast/readme.txt new file mode 100644 index 0000000..a354b6e --- /dev/null +++ b/misc/dreamcast/readme.txt @@ -0,0 +1,9 @@ +The dreamcast build requires an initial bootstrap program (Initial Program) named IP.bin + +To generate a custom IP.bin, compile https://github.com/Dreamcast-Projects/makeip + +Then run: makeip ip.txt IP.BIN -l boot_logo.png + +--- + +For more details about IP.bin, see https://mc.pp.se/dc/ip.bin.html \ No newline at end of file |