start: jp start1 .byte "Starfield demo (c) 2015 Bisqwit",0 start1: cls ld ve,1 ld v8, SHR(init_text,8) : ld v9, AND(init_text,255) ld v6,0 : ld v7,0 call render_text call init_stardata cls @loop: call iter ld v0, 1: call frame_delay ld v0, 0 @ktest: if key v0 : jp @kend add v0, 1 : if v0 <> 16 : jp @ktest jp @loop @kend: ld v8, SHR(done_text,8) : ld v9, AND(done_text,255) ld v6,0 : ld v7,0 call render_text exit ; schip48 instruction @end: jp @end init_stardata: call init_starptr ld v4, 0xFF ld v5, 0xFF ld vd, num_stars @loop: add vd,-1 rnd v0, 0xFF rnd v1, 0xFF rnd v2, 0xFF ld [i], v5 if vd = 0 : ret call dec_starptr jp @loop iter: call init_starptr ld vd, num_stars @loop: add vd,-1 ld v5, [i] ld v7,v0 ld v8,v1 ld v9,v2 ld v0,vd: ld [@starno], v0 ; Loaded: v7 = 3D x ; signed ; v8 = 3D y ; signed ; v9 = 3D z ; unsigned ; v3 = 2D sx ; v4 = 2D sy ; v5 = 2D ptr hi ; v6 = 2D ptr lo ; Unrender old star: call render_one ; Calculate v3 = 32 + v7*32/v9 ; Calculate v4 = 16 + v8*16/v9 ; Temps we can use: ; v0,v1,v2, va,vb,vc,vd ld v0,v7 call make_unsigned call make_16bit call multiply_32 call div_v9 call make_signed add v2, 32-4 ld v3, v2 ld v0,v8 call make_unsigned call make_16bit call multiply_16 call div_v9 call make_signed add v2, 16-3 ld v4, v2 ; Decide kind of star call decide_starkind ; Render current star: call render_one add v9,-warp ; Save modified star data call load_starptr ld v0, v7 ld v1, v8 ld v2, v9 ld [i], v5 ; Process next star ld vd,0x80 @starins: @starno = @starins - 1 if vd = 0 : ret call dec_starptr jp @loop render_one: ld v0,v3 : ld v1, 0xFF-63 : and v0,v1: if v0<>0 : jp @ret ld v0,v4 : ld v1, 0xFF-31 : and v0,v1: if v0<>0 : jp @ret ld v0,v5 : add v0, 0xA0 ld v1,v6 ld [@drw_i], v1 @drw_i: ld i,0xAAA drw v3,v4,5 @ret: ret init_starptr: ld v0, SHR(stardata+0xA000 + (num_stars-1)*star_recsize, 8) ld v1, AND(stardata+0xA000 + (num_stars-1)*star_recsize, 255) ld [load_starptr], v1 jp load_starptr dec_starptr: ld v2, star_recsize ld v1, [load_starptr] sub v1, v2 if vf=0 : sub v0, ve ld [load_starptr], v1 load_starptr: ld i, 0xAAA ret decide_starkind: ; set v5_v6 point to correct sprite ; depending on distance (v9) ; Use v0,v1 as temp ;ld v0, v9 ;ld v1, 8 : sub v0, v1 : if vf=0 : jp @near ;ld v1, 40: sub v0, v1 : if vf=0 : jp @mid @far: ld v5, SHR(farstar,8) : ld v6, AND(farstar,255) : ret ;@mid: ld v5, SHR(midstar,8) : ld v6, AND(midstar,255) : ret ;@near: ld v5, SHR(closestar,8) : ld v6, AND(closestar,255) : ret div_v9: ; Divide v0_v1 by v9. ; Use v4,va,vb,vc,vd as temps. ; v0_v1: remain ; va_vb: part1 ; vc_vd: mask ; v2: result (0-7F). If result > 7F, will be clamped to 7F. ld va,0 : ld vb,v9 ; va_vb = divisor = v9 if vb=0 : jp @overflow ld vc,0 : ld vd,1 ; vc_vd = mask = 1 @loop1: shl va,va : shl vb,vb : if vf<>0 : or va,ve shl vc,vc : shl vd,vd : if vf<>0 : or vc,ve ld v4,va : shl v4,v4 : if vf=0 : jp @loop1 ld v2,0 ; result = 0 @loop2: ; if(remain >= part1), goto @sub, else goto @skip ; if(remain < part1), goto @skip, else goto @sub ld v4,v0 : sub v4,va : if vf=0 : jp @skip if v4<>0 : jp @sub ld v4,v1 : sub v4,vb : if vf=0 : jp @skip @sub: ; remain -= part1 sub v0,va : sub v1,vb : if vf=0 : sub v0,ve ; result += mask add v2,vd : if vf=1 : jp @overflow if vc<>0: jp @overflow @skip: ; part1 >>= 1 shr vb,vb : shr va,va : if vf<>0: add vb,0x80 ; mask >>= 1 shr vd,vd : shr vc,vc : if vf<>0: add vd,0x80 ; if mask <> 0, goto @loop2 if vd <> 0 : jp @loop2 if vc <> 0 : jp @loop2 ld v0,v2 shl v0,v0: if vf=0: ret @overflow: ld v2,0x7F ret multiply_32: shl v0,v0 : shl v1,v1 : if vf<>0 : or v0,ve multiply_16: shl v0,v0 : shl v1,v1 : if vf<>0 : or v0,ve multiply_8: shl v0,v0 : shl v1,v1 : if vf<>0 : or v0,ve multiply_4: shl v0,v0 : shl v1,v1 : if vf<>0 : or v0,ve multiply_2: shl v0,v0 : shl v1,v1 : if vf<>0 : or v0,ve ret make_16bit: ld v1,v0 : ld v0,0 ret make_unsigned: ; Input: v0 ; Output: v0 = abs(v0). ; !sign will be saved in was_unsigned. ; Temps: v1,vf ld v1,v0 ld i, was_unsigned shl v0,v0 ld v0,1 if vf=0 : jp @done ld v0,0 subn v1,v0 ; Negate v1 = 0-v1 @done: ld [i],v0 ld v0,v1 ret make_signed: ; Input: v2 ; Output: v2 or -v2 ; Temps: v0 ld v0, 0x80 @ins: was_unsigned = @ins - 1 if v0 = 0 : subn v2, v0 ret frame_delay: ; v0 = number of frames to wait ld dt, v0 @wait: ld v0, dt : if v0 != 0 : jp @wait ret render_text: ; Input: v8=hi, v9=lo = address of text ; v6,v7 = x & y coordinates to render at ; Temps: ; v0,v1 = character index & font pointer ; v2,v3 = temp word ; v4 = backup of v6 add v8, 0xA0 ; ld i, imm ld v4, v6 @next_char: ld v0, v8 : ld v1, v9 : ld [@text_ptr], v1 @text_ptr: ; Load character from string ld v0, [0xAAA] ; self-modifying code if v0 = 0 : ret ld v2, -32 add v0, v2 : if vf=0 : jp @newline ; Multiply by 6 to turn into an offset to font6x5. ; Note: This will overflow into two bytes. ld v1, v0 : ld v0, 0 ; First multiply by two into v1,v0. c = orig*2 shl v1,v1 : if vf!=0 : or v0,ve ; Make copy. d = c ld v2,v0 : ld v3,v1 ; c *= 2 shl v0,v0: shl v1,v1 : if vf!=0 : or v0,ve ; Now c = orig*4, d = orig*2. Do c += d add v0, v2 add v1, v3 : if vf!=0 : add v0,1 ; Then, c += font6x5 add v0, SHR(font6x5, 8)+0xA0 ld v2, AND(font6x5, 255) add v1, v2 : if vf!=0 : add v0,1 ld [@font_ptr], v1 @font_ptr: ; Load font width ld v0, [0xAAA] ; self-modifying code ;add i, ve drw v6,v7, 5 add v6,v0 ; Wait a couple of frames ;ld v0, 30 : call frame_delay @next_char_advance: ; Advance the font pointer add v9, ve : if vf!=0 : add v8, 1 jp @next_char @newline: ld v6, v4 add v7, 6 jp @next_char_advance font6x5: ; 6x5 font data, originally designed by Juha Nieminen for use in Joed: .byte 4, 0, 0, 0, 0, 0,3, 64, 64, 64, 0, 64,5, 80, 80, 0, 0, 0; 32 .byte 6, 80,248, 80,248, 80,6,112,160,112, 40,240,6,136, 16, 32, 64,136; 35 .byte 6, 96, 96,104,144,104,3, 64, 64, 0, 0, 0,4, 32, 64, 64, 64, 32; 38 .byte 4, 64, 32, 32, 32, 64,7, 72, 48,252, 48, 72,6, 32, 32,248, 32, 32; 41 .byte 3, 0, 0, 0, 64,128,5, 0, 0,240, 0, 0,3, 0, 0, 0, 0, 64; 44 .byte 6, 8, 16, 32, 64,128,6,112,152,168,200,112,4, 64,192, 64, 64,224; 47 .byte 5, 96,144, 32, 64,240,5,240, 16, 96, 16,224,5, 80,144,240, 16, 16; 50 .byte 5,240,128,224, 16,224,5, 96,128,224,144, 96,5,240, 16, 32, 32, 64; 53 .byte 5, 96,144, 96,144, 96,5, 96,144,112, 16, 96,3, 0, 64, 0, 64, 0; 56 .byte 3, 0, 64, 0, 64,128,4, 32, 64,128, 64, 32,4, 0,224, 0,224, 0; 59 .byte 4,128, 64, 32, 64,128,5, 96,144, 32, 0, 32,5, 96,144,176,128, 96; 62 .byte 5, 96,144,240,144,144,5,224,144,224,144,224,5,112,128,128,128,112; ABC .byte 5,224,144,144,144,224,5,240,128,224,128,240,5,240,128,224,128,128; DEF .byte 5,112,128,176,144,112,5,144,144,240,144,144,4,224, 64, 64, 64,224; GHI .byte 5, 16, 16, 16,144, 96,5,144,160,192,160,144,5,128,128,128,128,240; JKL .byte 6,136,216,168,136,136,6,136,200,168,152,136,5, 96,144,144,144, 96; MNO .byte 5,224,144,224,128,128,5, 96,144,144,176,112,5,224,144,224,160,144; PQR .byte 5, 96,128, 96, 16,224,6,248, 32, 32, 32, 32,5,144,144,144,144, 96; STU .byte 6,136,136, 80, 80, 32,6,136,136,136,168, 80,6,136, 80, 32, 80,136; VWX .byte 6,136, 80, 32, 32, 32,6,248, 16, 32, 64,248,3,192,128,128,128,192; YZ[ .byte 6,128, 64, 32, 16, 8,3,192, 64, 64, 64,192,4, 64,160, 0, 0, 0; \]^ .byte 5, 0, 0, 0, 0,240,3,128, 64, 0, 0, 0,5, 96, 16,112,144,112; _`a .byte 5,128,128,224,144,224,4, 0, 96,128,128, 96,5, 16, 16,112,144,112; bcd .byte 5, 0, 96,240,128, 96,4, 96,128,192,128,128,4, 0, 96,160, 96,192; efg .byte 5,128,128,224,144,144,4, 64, 0,192, 64,224,3, 64, 0, 64, 64,192; hij .byte 5,128,160,192,160,144,4,192, 64, 64, 64,224,6, 0,208,168,168,136; klm .byte 5, 0,224,144,144,144,5, 0, 96,144,144, 96,5, 0,224,144,224,128; nop .byte 5, 0,112,144,112, 16,4, 0, 96,128,128,128,5, 0,112,192, 48,224; qrs .byte 4, 64,224, 64, 64, 32,5, 0,144,144,144,112,6, 0,136,136, 80, 32; tuv .byte 6, 0,136,136,168, 80,5, 0,144, 96, 96,144,5, 0,144,112, 16, 96; wxy .byte 5, 0,240, 32, 64,240,4, 96, 64,128, 64, 96,3, 64, 64, 64, 64, 64; z{| .byte 4,192, 64, 32, 64,192,5, 80,160, 0, 0, 0; }~ init_text: .db "Initializing,",13, "please wait...",0 done_text: .db "Key pressed.",13, "Terminating.",0 farstar: .byte 0b00000000 .byte 0b00000000 .byte 0b00010000 .byte 0b00000000 .byte 0b00000000 midstar: .byte 0b00000000 .byte 0b00010000 .byte 0b00111000 .byte 0b00010000 .byte 0b00000000 closestar: .byte 0b00010000 .byte 0b01111100 .byte 0b11111110 .byte 0b01111100 .byte 0b00010000 num_stars = 64 star_recsize = 7 warp = 4 stardata: ; Record: ; 0 = 3D x ; 1 = 3D y ; 2 = 3D z ; 3 = 2D sx ; 4 = 2D sy ; 5 = 2D ptr ; size: 7