Created
February 13, 2022 06:33
-
-
Save samneggs/9500c74e49d42e99e79125a9b1dea711 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#----------------Based on YouTube-3DSage---------------------------------------- | |
#Full video: https://youtu.be/PC1RaETIx3Y | |
import gc9a01 | |
from machine import Pin, SPI, PWM, WDT | |
import framebuf | |
from time import sleep_ms, sleep_us, ticks_diff, ticks_us, sleep | |
from micropython import const | |
import array | |
from usys import exit | |
import gc | |
from math import sin,cos,pi,radians,tan | |
from random import randint | |
from uctypes import addressof | |
#-----------------------------MAP---------------------------------------------- | |
MAXSCREEN_X = const(240) | |
MAXSCREEN_Y = const(200) | |
MAXSCREEN = const(MAXSCREEN_X*MAXSCREEN_Y*2) | |
YMAX= const(400) #400 # 320 | |
mapX = const(8) #map width | |
mapY = const(8) #map height | |
mapS = const(64) #map cube size | |
SCALE = const(3) | |
UPDATE_SPEED = const(120)#20 | |
TEXTURES = const(1) | |
BLUE = const(0x1f00) | |
BLACK = const(0) | |
WHITE = const(0xffff) | |
GREEN = const(0xe00A) | |
BROWN = const(0xe091) | |
RED = const(0x07e0) | |
YELLOW=const(0x00fe) | |
TEXTURE_HEIGHT = const(32*8) #47 | |
TEXTURE_WIDTH = const(32) #90 | |
#------joystck pin declaration----- | |
joyRight = Pin(17,Pin.IN) | |
joyDown = Pin(18,Pin.IN) | |
joySel = Pin(19,Pin.IN) | |
joyLeft = Pin(20,Pin.IN) | |
joyUp = Pin(21,Pin.IN) | |
display_buffer=bytearray(MAXSCREEN_X * MAXSCREEN_Y * 2) | |
tex_buff=bytearray(TEXTURE_WIDTH*TEXTURE_HEIGHT*2) | |
from raycast_maps2 import mapW_array,mapF_array,mapC_array | |
char_map=array.array('b',( | |
0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00, # U+0030 (0) | |
0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00, # U+0031 (1) | |
0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00, # U+0032 (2) | |
0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00, # U+0033 (3) | |
0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00, # U+0034 (4) | |
0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00, # U+0035 (5) | |
0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00, # U+0036 (6) | |
0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00, # U+0037 (7) | |
0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00, # U+0038 (8) | |
0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00)) # U+0039 (9) | |
isin=array.array('i',range(0,361)) | |
icos=array.array('i',range(0,361)) | |
itan=array.array('i',range(0,361)) | |
# partx=array.array('i',range(0,100)) | |
# party=array.array('i',range(0,100)) | |
# partdx=array.array('i',range(0,100)) | |
# partdy=array.array('i',range(0,100)) | |
class Player(): | |
def __init__(self): | |
self.px = 350 | |
self.py = 250 | |
self.pdx = 0 | |
self.pdy = 0 | |
self.pa = 70 | |
self.floor = 0 | |
player=Player() | |
# http://www.penguintutor.com/programming/picodisplayanimations | |
def blit_image_file(filename,width,height,cw,ch): # file width, file height, char width, char height | |
print(filename,gc.mem_free()) | |
with open (filename, "rb") as file: | |
file_position = 0 | |
char_position = 0 | |
ecount = 0 | |
current_byte = file.read(4) # header | |
while file_position < (width * height * 2): | |
current_byte = file.read(1) | |
# if eof | |
if len(current_byte) == 0: | |
break | |
# copy to buffer | |
tex_buff[char_position] = ord(current_byte) #and LCD.red | |
char_position += 1 | |
file_position += 1 | |
#if char_position == (cw * ch* 2): | |
# char_position = 0 | |
file.close() | |
#screen.blit(texture,50,50) | |
#tft.blit_buffer(screen, 20, 0, MAXSCREEN_X, MAXSCREEN_Y) | |
#exit() | |
def init_isin(): # integer sin lookup table | |
for i in range(0,361): | |
isin[i]=int(sin(radians(i))*(1<<14)) | |
def init_icos(): # integer cos lookup table | |
for i in range(0,361): | |
icos[i]=int(cos(radians(i))*(1<<14)) | |
def init_itan(): # integer cos lookup table | |
for i in range(0,361): | |
itan[i]=int(tan(radians(i))*(1<<14)) | |
def bl_ctrl(duty): | |
pwm = PWM(Pin(13)) | |
pwm.freq(1000) | |
if(duty>=100): | |
pwm.duty_u16(65535) | |
else: | |
pwm.duty_u16(655*duty) | |
@micropython.viper | |
def screen_fps(n:int,p:int): | |
dest=ptr16(screen)#screen | |
c_map=ptr8(char_map) | |
huns = n//100 | |
tens = int((0xcc_cccd*n)>>27) # n//10 | |
ones = n-(tens*10) # n%10 | |
row = 8 | |
offset=p*8+50 | |
while(row): | |
row-=1 | |
col=8 | |
while(col): | |
col-=1 | |
r=(row*MAXSCREEN_X+col)+offset | |
#if c_map[(huns<<3)+row] & 1<<col: | |
# dest[r] = 0# 0xffff | |
if c_map[(tens<<3)+row] & 1<<col: | |
dest[r+8] = 0xffff | |
if c_map[(ones<<3)+row] & 1<<col: | |
dest[r+16] = 0xffff | |
def fade(input_color1, input_color2): | |
color1=input_color1<<8 | input_color1>>8 # byte swap to normal RBG565 | |
red1 =color1>>11& 0b11111 # extract red #13 | |
green1=color1>>6 & 0b11111 # extract green | |
blue1 =color1 & 0b11111 # extract blue | |
color2=input_color2<<8 | input_color2>>8 # byte swap | |
red2 =color2>>11& 0b11111 # extract red | |
green2=color2>>6 & 0b11111 # extract green | |
blue2 =color2 & 0b11111 # extract blue | |
inc_red =(red2- red1)/31 # find increment step | |
inc_green=(green2-green1)/31 | |
inc_blue =(blue2- blue1)/31 | |
for i in range(0,32): | |
red3 =red1 +int(i*inc_red) # build colors by steps | |
green3=green1+int(i*inc_green) | |
blue3 =blue1 +int(i*inc_blue) | |
color3=red3<<11 | green3<<6 | blue3 # combine RGB | |
color_l2.append((color3 & 0x00FF)<<8 | (color3>>8)) # byte swap to LCD RGB565 | |
def Buttons(fps): | |
pushed=0 | |
if(joyLeft.value() == 0): #(key=='a'): | |
player.pa=limit_deg(player.pa+UPDATE_SPEED//fps) | |
player.pdx=cos(radians(player.pa)) | |
player.pdy=-sin(radians(player.pa)) | |
#sprite.dx=int(player.pdx*(1<<14)) | |
#sprite.dy=int(player.pdy*(1<<14)) | |
if(joyRight.value() == 0): #(key=='d') | |
player.pa=limit_deg(player.pa-UPDATE_SPEED//fps) | |
player.pdx=cos(radians(player.pa)) | |
player.pdy=-sin(radians(player.pa)) | |
#sprite.dx=int(player.pdx*(1<<14)) | |
#sprite.dy=int(player.pdy*(1<<14)) | |
xo=0 | |
if(player.pdx<0): | |
xo=-20 | |
else: | |
xo=20 #x offset to check map | |
yo=0 | |
if(player.pdy<0): | |
yo=-20 | |
else: | |
yo=20 #y offset to check map | |
ipx=int(player.px>>6) | |
ipx_add_xo=int((player.px+xo)>>6) | |
ipx_sub_xo=int((player.px-xo)>>6) #x position and offset | |
ipy=int(player.py>>6) | |
ipy_add_yo=int((player.py+yo)>>6) | |
ipy_sub_yo=int((player.py-yo)>>6) #y position and offset | |
if(joyUp.value() == 0): #(key=='w'): | |
if(mapW_array[player.floor+ipy*mapX + ipx_add_xo]==0): | |
player.px+=int(player.pdx*UPDATE_SPEED//fps) #TURN_SPEED | |
if(mapW_array[player.floor+ipy_add_yo*mapX + ipx ]==0): | |
player.py+=int(player.pdy*UPDATE_SPEED//fps) | |
if(joyDown.value() == 0):#(key=='s'): | |
if(mapW_array[player.floor+ipy*mapX + ipx_sub_xo]==0): | |
player.px-=int(player.pdx*UPDATE_SPEED//fps) | |
if(mapW_array[player.floor+ipy_sub_yo*mapX + ipx ]==0): | |
player.py-=int(player.pdy*UPDATE_SPEED//fps) | |
if(joySel.value() == 0): | |
#screen.blit(texture,50,00) | |
if player.pdx<0: | |
xo=-25 | |
else: | |
xo=25 | |
if player.pdy<0: | |
yo=-25 | |
else: | |
yo=25 | |
ipx=player.px>>6 | |
ipx_add_xo=int((player.px+xo)>>6) | |
ipy=player.py>>6 | |
ipy_add_yo=int((player.py+yo)>>6) | |
#sprite.x=player.px<<14 | |
#sprite.y=player.py<<14 | |
# for i in range(100): | |
# partx[i]=player.px<<14 | |
# party[i]=player.py<<14 | |
# partdx[i]=int(player.pdx*(1<<14))+randint(-5000,5000) | |
# partdy[i]=int(player.pdy*(1<<14))+randint(-5000,5000) | |
# | |
if(mapW_array[player.floor+ipy_add_yo*mapX+ipx_add_xo]==4): | |
mapW_array[player.floor+ipy_add_yo*mapX+ipx_add_xo]=0 | |
if(mapW_array[player.floor+ipy_add_yo*mapX+ipx_add_xo]==5): | |
player.floor+=64 | |
gc.collect() | |
blit_image_file('floor'+str(player.floor>>6)+'.bin',32,32*8,32,32) | |
player.pa=limit_deg(player.pa+180) | |
return | |
if(mapW_array[player.floor+ipy_add_yo*mapX+ipx_add_xo]==6): | |
player.floor-=64 | |
gc.collect() | |
blit_image_file('floor'+str(player.floor>>6)+'.bin',32,32*8,32,32) | |
player.pa=limit_deg(player.pa+180) | |
return | |
@micropython.viper | |
def draw_walls(lineH:int,tx:int,ty:int,shade:int,hmt:int,r:int,lineOff:int,ty_step:int,disH:int): | |
dest=ptr16(screen) | |
color_addr=ptr16(color_l2) | |
#all_addr=ptr8(All_Textures_array) | |
texture_addr=ptr16(tex_buff) | |
walls_ctl_addr=ptr32(walls_ctl) | |
y=0 | |
r2=r<<2 | |
tx2=tx%(31) | |
shade2=30-(disH>>4) | |
walls_ctl_addr[0] = lineH | |
walls_ctl_addr[1] = tx2 | |
walls_ctl_addr[2] = ty | |
walls_ctl_addr[3] = shade2 | |
walls_ctl_addr[4] = hmt | |
walls_ctl_addr[5] = r2 | |
walls_ctl_addr[6] = lineOff | |
walls_ctl_addr[7] = ty_step | |
walls_ctl_addr[8] = disH | |
#walls_ctl_addr[9] = color | |
#walls_ctl_addr[10] = int(player.floor) | |
walls_ctl_addr[11] = 0x07e0f81f | |
walls_ctl_addr[12] = 0 #forground | |
walls_asm(dest,walls_ctl_addr,texture_addr) | |
return | |
LINEH_CTL = const(0) # lineH | |
TX2_CTL = const(4) # tx2 | |
TY_CTL = const(8) # ty | |
SHADE_CTL = const(12) # shade | |
HMT_CTL = const(16) # hmt | |
R2_CTL = const(20) # r2 | |
LINEOFF_CTL = const(24) # lineOff | |
TY_STEP_CTL = const(28) # ty_step | |
DISH_CTL = const(32) # disH | |
COLOR_CTL = const(36) # color2 | |
FLOOR_CTLx = const(40) # player.floor | |
MAGIC2_CTL = const(44) # 0x07e0f81f | |
FG2_CTL = const(48) # forground color | |
walls_ctl=array.array('i',(0,4,8,12,16,20,24,28,32,36,40,0x07e0f81f,48,0,0)) | |
@micropython.asm_thumb | |
def walls_asm(r0,r1,r2): # r0=screen, r1=CTL array, r2=texture_addr | |
ldr(r3,[r1,HMT_CTL]) # r4=hmt | |
cmp(r3,0) | |
beq(EXIT) | |
mov(r4,1) | |
lsl(r4,r4,11) # r4= 1<<11 = 2048 = 32*32*2 | |
mul(r4,r3) # r4= hmt * 2048 | |
add(r5,r2,r4) # r5= texture_addr += 32*32*2 | |
mov(r2,0) # r2=y | |
label(LOOP) | |
# pos=((y+lineOff)>>1)*MAXSCREEN_X+r2 | |
ldr(r3,[r1,LINEOFF_CTL]) # r3=lineOff | |
add(r3,r2,r3) # r3=y+lineOff | |
asr(r3,r3,1) # r3=(y+lineOff)>>1 | |
mov(r4,MAXSCREEN_X) | |
mul(r3,r4) # r3=(y+lineOff)>>1*MAXSCREEN_X | |
ldr(r4,[r1,R2_CTL]) | |
add(r3,r3,r4) # r4=(y+lineOff)>>1*MAXSCREEN_X+r2 | |
add(r3,r3,r3) # double for 2 bytes per pixel | |
add(r7,r3,r0) # dest[...] | |
# color2=texture_addr[(((ty>>14)-(((ty>>14)>>5)<<5))<<5) + tx2 ] | |
label(TEXTURE) | |
ldr(r3,[r1,TY_CTL]) # r3=ty | |
ldr(r4,[r1,TY_STEP_CTL]) # r4=ty_step | |
add(r4,r4,r3) # ty+=ty_step | |
str(r4,[r1,TY_CTL]) # | |
asr(r3,r3,14) # r3= ty>>14 | |
mov(r6,r3) # r6= ty>>14 | |
asr(r6,r6,5) # r6= (ty>>14)>>5 | |
lsl(r6,r6,5) # r6= ((ty>>14)>>5)<<5 | |
sub(r6,r3,r6) # r6= (ty>>14)-(((ty>>14)>>5)<<5) | |
lsl(r6,r6,5) # r6= (ty>>14)-(((ty>>14)>>5)<<5)<<5 | |
ldr(r3,[r1,TX2_CTL]) # r3=tx2 | |
add(r6,r3,r6) # r6= (ty>>14)-(((ty>>14)>>5)<<5) + tx2 | |
add(r6,r6,r6) # double for ldrh | |
add(r6,r5,r6) # r6= texture_addr[...] | |
ldrh(r6,[r6,0]) # r6= color | |
ldr(r3,[r1,HMT_CTL]) # r3=hmt | |
cmp(r3,6) | |
beq(DRAW_WALLS) # fire? skip shade | |
data(2,0b1011_1010_01_110_110) # r6=swap color bytes | |
mov(r3,r6) # r3,r6= fg | |
lsl(r6,r6,16) # fg << 16 | |
orr(r6,r3) # fg | (fg << 16) | |
ldr(r3,[r1,MAGIC2_CTL]) # 0x07e0f81f | |
and_(r3,r6) # r3=(fg | (fg << 16)) & 0x07e0f81f | |
ldr(r4,[r1,FG2_CTL]) # bg | |
lsl(r6,r4,16) # bg << 16 | |
orr(r6,r4) # bg | (bg << 16) | |
ldr(r4,[r1,MAGIC2_CTL]) # 0x07e0f81f | |
and_(r4,r6) # r4=(bg | (bg << 16)) & 0x07e0f81f | |
# bg = bg + (((fg-bg)*alpha)>> 5) | |
sub(r6,r3,r4) # (fg-bg) | |
ldr(r3,[r1,SHADE_CTL]) # alpha | |
mul(r6,r3) # ((fg-bg)*alpha) | |
asr(r6,r6,5) # (((fg-bg)*alpha)>> 5) | |
add(r4,r4,r6) # r4 = bg + (((fg-bg)*alpha)>> 5) | |
ldr(r3,[r1,MAGIC2_CTL]) | |
and_(r4,r3) # bg = bg & 0x07e0f81f | |
mov(r3,r4) # r3 = bg | |
asr(r4,r4,16) # (bg >> 16) | |
orr(r4,r3) # bg | (bg >> 16) | |
mov(r6,1) | |
lsl(r6,r6,16) # 1<<16 = 0x10000 | |
sub(r6,r6,1) # 0x10000-1 = 0xffff | |
and_(r4,r6) # r4 & 0xffff | |
mov(r6,r4) | |
label(DONE_SHADE) | |
data(2,0b1011_1010_01_110_110) # r6=swap color bytes | |
label(DRAW_WALLS) | |
strh(r6, [r7, 0]) # r7=screen | |
strh(r6, [r7, 2]) | |
strh(r6, [r7, 4]) | |
strh(r6, [r7, 6]) | |
add(r2,r2,1) # y+=1 | |
ldr(r3,[r1,LINEH_CTL]) | |
cmp(r2,r3) # while y<lineH: | |
blt(LOOP) | |
label(EXIT) | |
@micropython.viper | |
def draw_floor(y:int,px:int,py:int,fixang:int,deg:int,r:int,shade:int): | |
dest=ptr16(screen) | |
cos_addr=ptr32(icos) | |
sin_addr=ptr32(isin) | |
mapf_addr=ptr8(mapF_array) | |
mapc_addr=ptr8(mapC_array) | |
color_addr=ptr16(color_l2) | |
texture_addr=ptr16(tex_buff) | |
floor_ctl_addr=ptr32(floor_ctl) | |
px2=px>>1 | |
py2=py>>1 | |
cos_deg=(cos_addr[deg]*200)*32 #158*32 | |
sin_deg=(sin_addr[deg]*200)*32 | |
cos_fixang=cos_addr[fixang] | |
r4=r<<2 | |
floor_ctl_addr[0] = y | |
floor_ctl_addr[1] = px2 | |
floor_ctl_addr[2] = py2 | |
floor_ctl_addr[3] = cos_deg | |
floor_ctl_addr[4] = sin_deg | |
floor_ctl_addr[5] = cos_fixang | |
floor_ctl_addr[6] = r4 | |
#floor_ctl_addr[7] = tx | |
#floor_ctl_addr[8] = ty | |
floor_ctl_addr[9] = 0 #denominator | |
floor_ctl_addr[10] = 0 # forground | |
floor_ctl_addr[11] = 0x07e0f81f | |
floor_ctl_addr[12] = shade # not used | |
floor_asm(dest,texture_addr,floor_ctl_addr) | |
return | |
while(y<400): | |
dy=y-200 | |
tx=px2 + (cos_deg//(dy*cos_fixang)) | |
ty=py2 - (sin_deg//(dy*cos_fixang)) | |
#c=texture_addr[((ty%(32))*32) + (tx%(32))] | |
c=texture_addr[((ty-((ty>>5)<<5))<<5) + tx-((tx>>5)<<5) ] | |
pos=(y>>1)*MAXSCREEN_X+r4 | |
if pos<MAXSCREEN: | |
dest[pos]=c | |
dest[pos+1]=c | |
dest[pos+2]=c | |
dest[pos+3]=c | |
y+=2 | |
Y_CTL = const(0) # y | |
PX2_CTL = const(4) # px2 | |
PY2_CTL = const(8) # py2 | |
COS_DEG_CTL = const(12) # cos_deg | |
SIN_DEG_CTL = const(16) # sin_deg | |
COS_FIXANG_CTL = const(20) # cos_fixang | |
R4_CTL = const(24) # r4 | |
TX_CTL = const(28) # tx | |
TY_CTL2 = const(32) # ty | |
DENOM_CTL = const(36) # dy*cos_fixang | |
FG_CTL = const(40) # forground color | |
MAGIC_NUM_CTL = const(44) # 0x07e0f81f | |
ALPHA_CTL = const(48) # alpha | |
floor_ctl=array.array('i',(0,4,8,12,16,20,24,28,32,36,40,44,48,0,0)) | |
# y,px2,py2,cos_deg,sin_deg,cos_fixang,r4,tx,ty | |
@micropython.asm_thumb | |
def floor_asm(r0,r1,r2): # r0=screen, r1=texture_addr , r2=CTL array | |
align(2) | |
ldr(r6,[r2,Y_CTL]) # r6=y | |
# dy=y-200 | |
# tx=px2 + (cos_deg//(dy*cos_fixang)) | |
# ty=py2 - (sin_deg//(dy*cos_fixang)) | |
label(MAINLOOP) | |
push({r0,r1}) # save r0,r1 for divide | |
mov(r3,r6) | |
sub(r3,200) # r3 dy=y-200 | |
ldr(r4,[r2,COS_FIXANG_CTL]) # | |
mul(r4,r3) # r4=dy*cos_fixang | |
mov(r1,r4) # r1=dy*cos_fixang | |
str(r1,[r2, DENOM_CTL]) | |
ldr(r0,[r2,COS_DEG_CTL]) # r0=cos_deg | |
bl(DIVIDE) # cos_deg//(dy*cos_fixang) | |
ldr(r1,[r2,PX2_CTL]) # px2 | |
add(r0,r1,r0) # px2 + (cos_deg//(dy*cos_fixang)) | |
str(r0,[r2, TX_CTL]) # tx=px2 + (cos_deg//(dy*cos_fixang)) | |
ldr(r0,[r2,SIN_DEG_CTL]) # r0=sin_deg | |
ldr(r1,[r2,DENOM_CTL]) # r1=dy*cos_fixang | |
bl(DIVIDE) | |
ldr(r1,[r2,PY2_CTL]) # py2 | |
sub(r0,r1,r0) # py2 - (sin_deg//(dy*cos_fixang)) | |
str(r0,[r2,TY_CTL2]) # ty=py2 - (sin_deg//(dy*cos_fixang)) | |
# c=texture_addr[((ty-((ty>>5)<<5))<<5) + tx-((tx>>5)<<5) ] | |
mov(r1,r0) # r1=ty | |
asr(r0,r0,5) # r0= ty>>5 | |
lsl(r0,r0,5) # r0= (ty>>5)<<5 | |
sub(r0,r1,r0) # r0= (ty)- ((ty>>5)<<5) | |
lsl(r0,r0,5) # r0= (ty)-(((ty>>5)<<5)<<5 | |
ldr(r1,[r2,TX_CTL]) # r1=tx | |
mov(r3,r1) # r3=tx | |
asr(r1,r1,5) # tx>>5 | |
lsl(r1,r1,5) # (tx>>5)<<5 | |
sub(r1,r3,r1) # r1= (tx)-((tx>>5)<<5) | |
add(r4,r0,r1) # r4= (((ty)-(((ty>>5)<<5))<<5) + tx-((tx>>5)<<5) | |
pop({r0,r1}) # get r0,r1 back | |
add(r4,r4,r4) # double for color | |
add(r4,r4,r1) # add to texture base address | |
ldrh(r3,[r4,0]) # r3=color | |
data(2,0b1011_1010_01_011_011) # r3=swap color bytes | |
# fg = (fg | (fg << 16)) & 0b00000111111000001111100000011111 # 0x07e0f81f | |
# bg = (bg | (bg << 16)) & 0b00000111111000001111100000011111 # 0x07e0f81f | |
# bg = bg + (((fg-bg)*alpha)>> 5) | |
# bg = bg & 0x07e0f81f | |
# bg = bg | (bg >> 16) # gggbbbbb_rrrrrggg | |
# bg = (bg>>8) | ((bg<<8) & 0xffff) | |
mov(r5,r3) | |
lsl(r4,r5,16) # fg << 16 | |
orr(r4,r5) # fg | (fg << 16) | |
ldr(r5,[r2,MAGIC_NUM_CTL]) # 0x07e0f81f | |
and_(r5,r4) # r5=(fg | (fg << 16)) & 0x07e0f81f | |
ldr(r4,[r2,FG_CTL])#### # | |
# bg | |
lsl(r7,r4,16) # bg << 16 | |
orr(r7,r4) # bg | (bg << 16) | |
ldr(r4,[r2,MAGIC_NUM_CTL]) # 0x07e0f81f | |
and_(r4,r7) # r4=(bg | (bg << 16)) & 0x07e0f81f | |
# bg = bg + (((fg-bg)*alpha)>> 5) | |
sub(r5,r5,r4) # (fg-bg) | |
#ldr(r3,[r2,ALPHA_CTL]) # alpha | |
mov(r7,r6)###### | |
asr(r7,r7,3)#### | |
sub(r7,25) | |
mul(r5,r7) # ((fg-bg)*alpha)>> 5 | |
asr(r5,r5,5) # (((fg-bg)*alpha)>> 5) | |
add(r4,r4,r5) # r4 = bg + (((fg-bg)*alpha)>> 5) | |
ldr(r7,[r2,MAGIC_NUM_CTL]) | |
and_(r4,r7) # bg = bg & 0x07e0f81f | |
mov(r7,r4) # r7 = bg | |
asr(r4,r4,16) # (bg >> 16) | |
orr(r4,r7) # bg | (bg >> 16) | |
mov(r5,1) | |
lsl(r5,r5,16) # 1<<16 = 0x10000 | |
sub(r5,r5,1) # 0x10000-1 = 0xffff | |
and_(r4,r5) # r4 & 0xffff | |
mov(r3,r4) | |
label(DONE_SHADE) | |
data(2,0b1011_1010_01_011_011) # r4=swap color bytes | |
# pos=(y>>1)*MAXSCREEN_X+r4 | |
asr(r4,r6,1) # y>>1 | |
mov(r5,MAXSCREEN_X) # MAXSCREEN_X | |
mul(r4,r5) # (y>>1)*MAXSCREEN_X | |
ldrh(r5,[r2,R4_CTL]) | |
add(r4,r4,r5) # (y>>1)*MAXSCREEN_X+r4 | |
add(r4,r4,r4) # double | |
add(r4,r0,r4) # add to base address of screen | |
strh(r3,[r4,0]) | |
strh(r3,[r4,2]) | |
strh(r3,[r4,4]) | |
strh(r3,[r4,6]) | |
b(SKIP) # ceiling ------------------------ | |
mov(r7,200) # r7=200 | |
lsl(r7,r7,1) # r7=400 | |
sub(r7,r7,r6) # 400-y | |
asr(r4,r7,1) # y>>1 | |
mov(r5,MAXSCREEN_X) # MAXSCREEN_X | |
mul(r4,r5) # (y>>1)*MAXSCREEN_X | |
ldrh(r5,[r2,R4_CTL]) | |
add(r4,r4,r5) # (y>>1)*MAXSCREEN_X+r4 | |
add(r4,r4,r4) # double | |
add(r4,r0,r4) # add to base address of screen | |
strh(r3,[r4,0]) | |
strh(r3,[r4,2]) | |
strh(r3,[r4,4]) | |
strh(r3,[r4,6]) | |
label(SKIP) #------------end ceiling---------- | |
add(r6,r6,2) # y+=2 | |
mov(r7,200) # (y<400): | |
lsl(r7,r7,1) | |
cmp(r6,r7) | |
blt(MAINLOOP) | |
b(EXIT) | |
# -------------------divide routine----------r0=r0//r1------------- | |
label(DIVIDE) | |
mov(r3,0xd0) | |
lsl(r3,r3,24) # 0d0000000 | |
add(r3,0x60) # offset so strh will work | |
str(r0, [r3, 8]) # SIO_DIV_SDIVIDEND_OFFSET _u(0x00000068)8 / 60 unsigned | |
str(r1, [r3, 12]) # SIO_DIV_SDIVISOR_OFFSET _u(0x0000006c)12 / 64 | |
b(DELAY1) | |
label(DELAY1) | |
b(DELAY2) | |
label(DELAY2) | |
b(DELAY3) | |
label(DELAY3) | |
b(DELAY4) | |
label(DELAY4) | |
ldr(r1, [r3, 20]) #SIO_DIV_REMAINDER_OFFSET _u(0x00000074)20 | |
ldr(r0, [r3, 16]) #SIO_DIV_QUOTIENT_OFFSET _u(0x00000070)16 | |
bx(lr) | |
#----------------end divide------------------------------------- | |
label(EXIT) | |
@micropython.viper | |
def limit_deg(deg:int)->int: | |
if(deg>359): | |
deg-=360 | |
if(deg<0): | |
deg+=360 | |
return deg | |
#rx,ry,disV,vmt | |
RX_IND = const(0) | |
RY_IND = const(1) | |
DISV_IND = const(2) | |
VMT_IND = const(3) | |
output_array=array.array('i',(0,0,0,0)) | |
@micropython.viper | |
def test_ray1(ra:int): | |
cos_addr=ptr32(icos) | |
sin_addr=ptr32(isin) | |
tan_addr=ptr32(itan) | |
color_addr=ptr16(color_l2) | |
mapW_addr=ptr8(mapW_array) | |
outputs_addr=ptr32(output_array) | |
pa=int(player.pa) | |
px=int(player.px) | |
py=int(player.py) | |
vmt=0 | |
hmt=0 #vertical and horizontal map texture number | |
dof=0 | |
side=0 | |
disV=100000 | |
cos_ra=cos_addr[ra] | |
sin_ra=sin_addr[ra] | |
Tan=tan_addr[ra] | |
if cos_ra > 16: # 0.001: | |
rx=((px>>6)<<6)+64 | |
ry=(((px-rx)*Tan)>>14)+py | |
xo= 64 | |
yo=-1*((xo*Tan)>>14) #looking left | |
elif cos_ra< -16: #-0.001: | |
rx=((px>>6)<<6)-1 #-0.0001 <--!!!! | |
ry=(((px-rx)*Tan)>>14)+py | |
xo=-64 | |
yo=-1*((xo*Tan)>>14) #looking right | |
else: | |
rx=px | |
ry=py | |
dof=8 #looking up or down. no hit | |
while(dof<8): | |
mx=int(rx)>>6 | |
my=int(ry)>>6 | |
mp=my*mapX+mx | |
if(mp>0 and mp<mapX*mapY and mapW_addr[int(player.floor)+mp]>0): | |
vmt=mapW_addr[int(player.floor)+mp]-1 | |
dof=8 | |
disV=((cos_ra*(rx-px))>>14)-((sin_ra*(ry-py))>>14) #hit | |
else: | |
rx+=xo | |
ry+=yo | |
dof+=1 #check next horizontal | |
outputs_addr[RX_IND]=rx | |
outputs_addr[RY_IND]=ry | |
outputs_addr[DISV_IND]=disV | |
outputs_addr[VMT_IND]=vmt | |
# rx,ry,disV,vmt | |
@micropython.viper | |
def draw_rays(): | |
#int r,mx,my,mp,dof,side; float vx,vy,rx,ry,ra,xo,yo,disV,disH; | |
cos_addr=ptr32(icos) | |
sin_addr=ptr32(isin) | |
tan_addr=ptr32(itan) | |
color_addr=ptr16(color_l2) | |
mapW_addr=ptr8(mapW_array) | |
inputs_addr=ptr32(output_array) | |
pa=int(player.pa) | |
px=int(player.px) | |
py=int(player.py) | |
ra=int(limit_deg(pa+30)) #ray set back 30 degrees | |
for r in range(60): | |
#---Vertical--- | |
vmt=0 | |
hmt=0 #vertical and horizontal map texture number | |
dof=0 | |
disV=100000 | |
cos_ra=cos_addr[ra] | |
sin_ra=sin_addr[ra] | |
Tan=tan_addr[ra] | |
test_ray1(ra) | |
rx=int(inputs_addr[RX_IND]) | |
ry=int(inputs_addr[RY_IND]) | |
disV=int(inputs_addr[DISV_IND]) | |
vmt=int(inputs_addr[VMT_IND]) | |
vx=rx | |
vy=ry | |
#---Horizontal--- | |
dof=0 | |
disH=100000 | |
if Tan!=0: | |
Tan=((1<<28)//Tan) | |
if sin_ra> 16: #0.001: | |
ry=((py>>6)<<6) -1 #-0.0001 <--!!! | |
rx=(((py-ry)*Tan)>>14)+px | |
yo= -64 | |
xo=-1*((yo*Tan)>>14) #looking up | |
elif sin_ra < -16: #-0.001: | |
ry=((py>>6)<<6)+64 | |
rx=(((py-ry)*Tan)>>14)+px | |
yo= 64 | |
xo=-1*((yo*Tan)>>14) #looking down | |
else: | |
rx=px | |
ry=py | |
dof=8 #looking straight left or right | |
while(dof<8): | |
mx=rx>>6 | |
my=ry>>6 | |
mp=my*mapX+mx | |
if(mp>0 and mp<(mapX*mapY) and mapW_addr[int(player.floor)+mp]>0): | |
hmt=mapW_addr[int(player.floor)+mp]-1 | |
dof=8 | |
disH=((cos_ra*(rx-px))>>14)-((sin_ra*(ry-py))>>14) | |
else: | |
rx+=xo | |
ry+=yo | |
dof+=1 #check next horizontal | |
shade=1 | |
color=RED | |
if(disV<disH): | |
hmt=vmt | |
shade=2 # 0.5 | |
rx=vx | |
ry=vy | |
disH=disV | |
#screen.line(int(px//SCALE),int(py//SCALE),int(rx//SCALE),int(ry//SCALE),GREEN) #draw 2D ray | |
ca=int(limit_deg(pa-ra)) | |
disH=(disH*cos_addr[ca])>>14 #fix fisheye | |
lineH = ((mapS*YMAX))//disH | |
if lineH!=0: | |
ty_step=(32<<14)//lineH | |
ty_off=0 | |
if(lineH>YMAX): | |
ty_off=(lineH-YMAX)>>1 | |
lineH=YMAX #Line height and limit | |
lineOff = int(200 - (lineH>>1)) #line offset (160) | |
#Draw Walls | |
tx=0 | |
ty=(ty_off*ty_step)+((hmt*32)<<14) | |
if shade==1: | |
tx=int(rx>>1)%32 | |
if ra>180: | |
tx=31-tx | |
else: | |
tx=int(ry>>1)%32 | |
if ra>90 and ra<270: | |
tx=31-tx | |
draw_walls(lineH,tx,ty,shade,hmt,r,lineOff,ty_step,disH) # 800uS | |
#---draw floors--- | |
y=lineOff+lineH | |
fixang=int(limit_deg(pa-ra)) | |
draw_floor(y,px,py,fixang,ra,r,disH>>4) | |
#screen.fill_rect((r*4),lineOff//SCALE,4,(lineH)>>1,color_addr[int(disH)>>4]) # fast shaded line walls KEEP | |
ra=int(limit_deg(ra-1)) #go to next ray | |
fire_rgb = array.array('H',(8192 ,24616 ,41040 ,57456 ,24729 ,8378 ,24794 , | |
41178 ,57554 ,25035 ,57803 ,8900 ,41924 , | |
58300 ,9405 ,26037 ,42677 ,62430 ,65535)) | |
fire_buff=bytearray(32*32*2) | |
W_TEXTURE = const(4) | |
W_FIRE = const(8) | |
W_COLOR = const(12) | |
W_RANDINT = const(16) | |
@micropython.asm_thumb | |
def fire_asm(r0): # fire_ctl (tex_buff,fire_buff,color_l2) | |
mov(r1,31*2) #31 # r1=x | |
lsl(r4,r1,5) # 31*32 | |
label(BASELINE) | |
ldr(r2,[r0,W_FIRE]) # r2= fire_buff[] address | |
mov(r3,15*2) # color index 15*2 | |
add(r2,r2,r4) | |
add(r2,r2,r1) # | |
strh(r3,[r2,0]) # fire_buff[index]=15*2 | |
sub(r1,r1,2) # index-=2 | |
cmp(r1,0) | |
bge(BASELINE) | |
mov(r1,0) # r1=x | |
label(X_LOOP) | |
mov(r2,0) # r2=y | |
label(Y_LOOP) | |
lsl(r3,r2,5) # y*32 | |
add(r3,r3,r1) # y*32+x | |
add(r3,r3,r3) # double for ldrh | |
ldr(r5,[r0,W_FIRE]) # fire_addr[] | |
cmp(r3,0) | |
ble(NO_64) | |
add(r3,r3,r5) # r3=fire_addr[f_from] address | |
mov(r5,64) | |
sub(r5,r3,r5) | |
b(NO_64_ELSE) | |
label(NO_64) | |
add(r3,r3,r5) | |
#sub(r5,r3,r5) # r5=fire_addr[f_from-32] address | |
label(NO_64_ELSE) | |
ldrh(r4,[r3,0]) # r4=fire_addr[f_from] data | |
cmp(r4,0) | |
bgt(NOTZERO)#bne | |
mov(r6,0) | |
strh(r6,[r5,0]) # r5=fire_addr[f_from-32]=0 | |
b(DONE) | |
label(NOTZERO) | |
ldr(r6,[r0,W_RANDINT]) # randint(0,3)) | |
ldr(r7,[r6,0]) # reads one random bit | |
lsl(r7,r7,1) | |
ldr(r6,[r6,0]) | |
orr(r6,r7) | |
add(r6,r6,r6) # double | |
add(r5,r5,2) | |
sub(r5,r5,r6) | |
ldr(r6,[r0,W_RANDINT]) # randint(0,3)) & 1 | |
ldr(r7,[r6,0]) # reads one random bit | |
lsl(r7,r7,1) | |
ldr(r6,[r6,0]) | |
orr(r6,r7) | |
mov(r7,1) | |
and_(r6,r7) # randint(0,3)) & 1 | |
add(r6,r6,r6) # double | |
sub(r4,r4,r6) | |
cmp(r4,0)##### | |
blt(DONE)##### | |
strh(r4,[r5,0]) # r5=fire_addr[f_from+32]=fire_addr[f_from] | |
ldr(r6,[r0,W_COLOR]) # rgb_addr[] address | |
add(r6,r6,r4) # rgb_addr[fire_addr[f_to]] | |
mov(r7,1) | |
bic(r6,r7) | |
ldrh(r7,[r6,0]) # r7=rgb_addr[fire_addr[f_to]] | |
ldr(r6,[r0,W_TEXTURE]) # texture_addr[] address | |
mov(r3,6) # | |
lsl(r3,r3,10) # 6<<10= 32*32*6 | |
lsl(r5,r2,5) # r5= y*32 | |
add(r5,r5,r1) # = y*32+x | |
add(r5,r5,r3) # = y*32+x+32*32*2*2 | |
#sub(r5,32) | |
#add(r5,32)##### | |
add(r5,r5,r5) # double for strh | |
add(r5,r5,r6) # texture_addr[32*32*2+y*32+x] | |
strh(r7,[r5,0]) # texture_addr[-32+32*32*6+y*32+x] = rgb_addr[fire_addr[f_to]] | |
label(DONE) | |
add(r2,r2,1) # | |
cmp(r2,32) #31 | |
blt(Y_LOOP) # next y | |
add(r1,r1,1) | |
cmp(r1,31) #32 | |
blt(X_LOOP) # next x | |
label(EXIT) | |
water_buff=bytearray(32*32*2) | |
#W_TEXTURE = const(4) | |
W_WATER = const(8) | |
#W_COLOR = const(12) | |
#W_RANDINT = const(16) | |
@micropython.asm_thumb | |
def water_asm(r0): # water_ctl (tex_buff,water_buff,color_l2) | |
mov(r1,30*2) # r1=x | |
label(BASELINE) | |
ldr(r2,[r0,W_WATER]) # r2= water_buff[] address | |
mov(r3,15*2) # color index 15*2 | |
add(r2,r2,r1) # | |
strh(r3,[r2,0]) # water_buff[index]=15*2 | |
sub(r1,r1,2) # index-=2 | |
cmp(r1,0) | |
bge(BASELINE) | |
mov(r1,31) # r1=x | |
label(X_LOOP) | |
mov(r2,31) # r2=y | |
label(Y_LOOP) | |
lsl(r3,r2,5) # y*32 | |
add(r3,r3,r1) # y*32+x | |
add(r3,r3,r3) # double for ldrh | |
ldr(r5,[r0,W_WATER]) # water_addr[] | |
add(r3,r3,r5) # r3=water_addr[f_from] address | |
ldrh(r4,[r3,0]) # r4=water_addr[f_from] data | |
mov(r5,64) | |
add(r5,r5,r3) # r5=water_addr[f_from+32] address | |
cmp(r4,0) | |
bne(NOTZERO) | |
mov(r6,0) | |
strh(r6,[r5,0]) # r5=water_addr[f_from+32]=0 | |
b(DONE) | |
label(NOTZERO) | |
ldr(r6,[r0,W_RANDINT]) # randint(0,3)) & 1 | |
ldr(r7,[r6,0]) # reads one random bit | |
lsl(r7,r7,1) | |
ldr(r6,[r6,0]) | |
orr(r6,r7) | |
mov(r7,1) | |
and_(r6,r7) # randint(0,3)) & 1 | |
add(r6,r6,r6) # double | |
sub(r4,r4,r6) | |
strh(r4,[r5,0]) # r5=water_addr[f_from+32]=water_addr[f_from] | |
ldr(r6,[r0,W_COLOR]) # rgb_addr[] address | |
mov(r7,24) # 12*2 | |
add(r6,r6,r7) | |
add(r6,r6,r4) # rgb_addr[water_addr[f_to]] | |
mov(r7,1) | |
bic(r6,r7) | |
ldrh(r7,[r6,0]) # r7=rgb_addr[water_addr[f_to]+12] | |
ldr(r6,[r0,W_TEXTURE]) # texture_addr[] address | |
mov(r3,1) # | |
lsl(r3,r3,11) # 1<<11=2048 32*32*2 | |
lsl(r5,r2,5) # r5= y*32 | |
add(r5,r5,r1) # = y*32+x | |
add(r5,r5,r3) # = y*32+x+32*32*2*2 | |
add(r5,r5,r5) # double for strh | |
add(r5,r5,r6) # texture_addr[32*32*2+y*32+x] | |
strh(r7,[r5,0]) # texture_addr[32*32*2+y*32+x] = rgb_addr[water_addr[f_to]+12] | |
label(DONE) | |
sub(r2,r2,1) # | |
bpl(Y_LOOP) # next y | |
sub(r1,r1,1) | |
bpl(X_LOOP) # next x | |
label(EXIT) | |
if __name__=='__main__': | |
spi = SPI(1, baudrate=63_000_000, sck=Pin(10), mosi=Pin(11)) | |
tft = gc9a01.GC9A01( | |
spi, | |
MAXSCREEN_X, | |
240, | |
reset=Pin(12, Pin.OUT), | |
cs=Pin(9, Pin.OUT), | |
dc=Pin(8, Pin.OUT), | |
backlight=Pin(13, Pin.OUT), | |
rotation=0) | |
tft.init() | |
tft.rotation(0) | |
tft.fill(gc9a01.BLACK) | |
bl_ctrl(50) | |
sleep(0.5) | |
screen=framebuf.FrameBuffer(display_buffer, MAXSCREEN_X , MAXSCREEN_Y, framebuf.RGB565) | |
texture=framebuf.FrameBuffer(tex_buff,TEXTURE_WIDTH,TEXTURE_HEIGHT,framebuf.RGB565) | |
blit_image_file('floor'+str(player.floor>>6)+'.bin',32,32*8,32,32) | |
fps=0 | |
color_l2 = array.array('H', []) | |
fade(WHITE,BLUE) # 0 | |
init_isin() | |
init_icos() | |
init_itan() | |
wdt = WDT(timeout=8300) # Watchdog timer reset | |
gticks=ticks_us() | |
water_ctl=array.array('I',(0,addressof(tex_buff),addressof(water_buff),addressof(color_l2),0x4006001c,0,0,0)) | |
fire_ctl =array.array('I',(0,addressof(tex_buff),addressof( fire_buff),addressof(fire_rgb),0x4006001c,0,0,0)) | |
while(1): | |
wdt.feed() | |
screen.fill_rect(0,0,MAXSCREEN_X-1,90,BLACK) #1480 uS sky | |
#screen.fill_rect(0,90,MAXSCREEN_X,MAXSCREEN_X-50,GREEN) #solid floor | |
draw_rays() # 50000 uS | |
Buttons(fps+1) # 800uS | |
screen_fps(fps,8) # 180uS | |
water_asm(water_ctl) | |
fire_asm(fire_ctl) | |
tft.blit_buffer(screen, 0, 20, MAXSCREEN_X, MAXSCREEN_Y) # 16600uS 240x200 | |
fps=1_000_000//ticks_diff(ticks_us(), gticks) | |
gticks=ticks_us() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment