#include "library/cvboot.bas"
#include "library/smsvdp.bas"
#include "library/smsfilvrm.bas"
#include "library/smsldirvm.bas"
#include "library/smsvpoke.bas"
#include "library/sg1000putsprite.bas"
#include "library/smswaitvbl.bas"
#include "library/smsrnd.bas"
#include "library/librewayconvxwindows8x16font_charsetsprites.bas"
#include "library/cvjoypad.bas"

'-------------------------------------------------------------------------------
'- Numeric Maze
'- 2008, Mircea Petza (original version)
'- 2017, Paulo Silva (Colecovision version)
'-------------------------------------------------------------------------------
'- bugs:
'- 1: add game over?
'- 2: clean code
'-------------------------------------------------------------------------------

'- check which variables are not being used - colecovision ram starts at $7000 (1kb mirrored along)
dim eee as uinteger at $7010
dim seed as uinteger at $7012
dim ee0 as uinteger at $7014
dim ee1 as uinteger at $7016
dim ee2 as uinteger at $7018
dim ee3 as uinteger at $701A
dim ee4 as uinteger at $701C
dim ee5 as uinteger at $701E
dim kprs as uinteger at $7020
dim xpos as uinteger at $7022
dim ypos as uinteger at $7024
dim xposo as integer at $7026
dim yposo as uinteger at $7028
dim yposf as uinteger at $702A
dim tmcntr as uinteger at $702C
dim tmcntrs as uinteger at $702E
dim arrvl as uinteger at $7030
dim kpram as uinteger at $7032
dim score as uinteger at $7034
dim hiscore as uinteger at $7036

dim debug as ubyte at $703C
dim pldirct as ubyte at $703D
dim stage as ubyte at $703E
dim invjoypad as ubyte at $703F

'- maze area at $7100..$71FF
'- some temporary array at $7080..$708F

seed=4143
hiscore=0
debug=0
pldirct=0

'-------------------------------------------------------------------------------
'- subs

sub nops():
  asm
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    end asm
  end sub

sub putchar2x1(txlc as uinteger,tylc as uinteger,tch1 as ubyte):
  nops():nops()
  smsvpoke($1800+txlc+(tylc*32),tch1 )
  nops():nops()
  smsvpoke($1820+txlc+(tylc*32),tch1+128 )
  nops():nops()
  end sub

sub print2x1(txlc as uinteger,tylc as uinteger,tlad as uinteger,tlen as uinteger):
  nops()
  dim tllp as uinteger at $700E
  for tllp=0 to tlen-1
    smsvpoke($1800+txlc+(tylc*32)+tllp,peek(tlad+tllp) )
    smsvpoke($1820+txlc+(tylc*32)+tllp,peek(tlad+tllp)+128 )
    next
  nops()
  end sub

sub printdec2x2d4(txv2 as uinteger,tyv2 as uinteger,tvl2 as uinteger):
  nops()
  putchar2x1(txv2+0,tyv2,48+(int(tvl2/1000) mod 10))
  putchar2x1(txv2+1,tyv2,48+(int(tvl2/100) mod 10))
  putchar2x1(txv2+2,tyv2,48+(int(tvl2/10) mod 10))
  putchar2x1(txv2+3,tyv2,48+(tvl2 mod 10))
  nops()
  end sub

sub printdec2x2d2(txv2 as uinteger,tyv2 as uinteger,tvl2 as uinteger):
  nops()
  putchar2x1(txv2+0,tyv2,48+(int(tvl2/10) mod 10))
  putchar2x1(txv2+1,tyv2,48+(tvl2 mod 10))
  nops()
  end sub

sub filltile(txp1 as uinteger,typ1 as uinteger,txs1 as uinteger,tys1 as uinteger,tch1 as ubyte):
  nops()
  dim tllp as uinteger at $700E
  for tllp=typ1 to typ1+tys1-1
    smsfilvrm(6144+(tllp*32+txp1),tch1,txs1)
    next
  nops()
  end sub

sub putarray(txp1 as uinteger,typ1 as uinteger,txs1 as uinteger,tad1 as uinteger,tvl1 as ubyte):
  poke tad1+(typ1*txs1)+txp1,tvl1
  end sub

function getarray(txp2 as uinteger,typ2 as uinteger,txs2 as uinteger,tad2 as uinteger):
  return peek(tad2+(typ2*txs2)+txp2)
  end function

sub bintiles(txp1 as uinteger,typ1 as uinteger,tvl1 as ubyte,tch1 as ubyte,tch2 as ubyte):
  dim tlq1 as ubyte at $7000
  dim tvt1 as ubyte at $7002
  tlq1=128
  for tlb1=0 to 7
    tvt1=tch1
    if (tlq1 band tvl1)<>0 then:tvt1=tch2:end if
    smsvpoke($1800+txp1+tlb1+(typ1*32),tvt1)
    tlq1=tlq1/2
    next
  end sub

sub smoothspritemove(txp3 as ubyte,typ3 as ubyte,tdr1 as ubyte,tdf1 as ubyte)
  dim tlp1 as ubyte at $7000
  dim txq1 as byte at $7001
  dim tyq1 as byte at $7002
  txq1=0:tyq1=0
  for tlp1=0 to 8
    if tdr1=1 then:tyq1=tyq1-1:end if
    if tdr1=5 then:tyq1=tyq1+1:end if
    if tdr1=3 then:txq1=txq1+1:end if
    if tdr1=7 then:txq1=txq1-1:end if
    sg1000putsprite(0,(2+xpos)*8+txq1,(ypos)*16-1+tyq1,(tlp1 mod 4)*4+(tdf1*16),3)
    smswaitvbl(1)
    tmcntr=tmcntr+1
    next
  end sub

start01:
'-------------------------------------------------------------------------------
'- display

'msxscreen(1,2,0,0)
'- i dont know about these vdp entries, i have to fix it
smsvdp(0,$00):smsvdp(1,$E2) '- screen1,2
smsvdp(2,$06):smsvdp(3,$80):smsvdp(4,$00)
smsvdp(5,$36):smsvdp(6,$07)

' msxcolor(3,5,1) ----????
smsvdp(7,$31) 'smsvdp(7,F*16+4) '- ink*16+border - color(3,?,1)

'- mastergear needs this, i wonder why... :S 
smsfilvrm($0000,0,$4000)

'----
'- tiles and attributes
smsldirvm($0000,@charset01,2048)
smsfilvrm($2000,$1F,2048) '-?

'----
'- sprites

nops()
for ee1=0 to 15:smsldirvm($3800+(ee1*32),@sprites01+(ee1*16),16):next
nops()

'----
'- attributes
smsvpoke($2000,$9E):smsvpoke($2001,$FE):smsvpoke($2002,$FE):smsvpoke($2003,$FE)
smsvpoke($2010,$6E):smsvpoke($2011,$4E):smsvpoke($2012,$E6):smsvpoke($2013,$16)

'---
'- brick tiles 
smsldirvm($0480,@tilebrick01,8)
smsldirvm($04C0,@tilebrick01,8)

'-------------------------------------------------------------------------------

'- show all characters and sprites on screen when debug<>0
if debug<>0 then:
  for ee1=0 to 3
    for ee2=0 to 31
      smsvpoke($1800+ee2+(ee1*64),ee2+(ee1*32))
      smsvpoke($1820+ee2+(ee1*64),128+ee2+(ee1*32))
      next:next
  smswaitvbl(5)
  end if

'- define sprites????
for ee1=0 to 15
  for ee2=0 to 15
    smsvpoke($3800+ee2+(ee1*32),peek(@sprites01+ee2+(ee1*16)))
    next:next

'-------------------------------------------------------------------------------
'- title
smsfilvrm(6144,128+16,768)

'- Numeric Maze
print2x1(1,5,@text02a,@text02b-@text02a)

'- Original version - Mircea Petza, 2008
print2x1(1,10,@text02b,@text02c-@text02b)
print2x1(10,10,@text02d,@text02e-@text02d)
print2x1(3,12,@text02e,@text02f-@text02e)

'- Colecovision version - Paulo Silva, 2017
print2x1(1,15,@text02c,@text02d-@text02c)
print2x1(14,15,@text02d,@text02e-@text02d)
print2x1(3,17,@text02f,@text02g-@text02f)

'- push any key
print2x1(1,21,@text02g,@text02h-@text02g)

do
tmcntr=tmcntr+1
invjoypad=15-((cvjoypad1b() band cvjoypad2b()) band 15)
if invjoypad=0 then:
  else
    goto leavetitle01
  end if
loop

leavetitle01:
seed=seed+tmcntr

'-------------------------------------------------------------------------------
'- game loop

stage=1:score=0

do
smsfilvrm(6144,128+16,768)

for ee1=$7100 to $71FF
  eee=smsrnd(eee)
  poke ee1,eee mod 10
  poke ee1,0
  next

'-----
'- generate random array
for ee1=0 to 9
  for ee2=0 to 18
    seed=smsrnd(seed)
    putarray(ee2,ee1,19,$7100,seed mod 10)
    next:next

'-----
'- fixing generated random array
for ee5=0 to 1 '- this part is slowing down a lot, check how many are enough
  for ee1=0 to 8
    for ee2=0 to 17
      ee3=peek($7100+ee1*19+ee2):ee4=peek($7100+ee1*19+ee2+20)
      if ee3=ee4 then:putarray(ee2+1,ee1+1,19,$7100,(ee3+1) mod 10):end if
      next:next
  for ee1=0 to 8
    for ee2=1 to 18
      ee3=peek($7100+ee1*19+ee2):ee4=peek($7100+ee1*19+ee2+18)
      if ee3=ee4 then:putarray(ee2-1,ee1+1,19,$7100,(ee3+1) mod 10):end if
      next:next
  for ee1=0 to 9
    for ee2=0 to 16
      ee3=peek($7100+ee1*19+ee2):ee4=peek($7100+ee1*19+ee2+2)
      if ee3=ee4 then:putarray(ee2+2,ee1+0,19,$7100,(ee3+1) mod 10):end if
      next:next
  for ee1=0 to 7
    for ee2=0 to 18
      ee3=peek($7100+ee1*19+ee2):ee4=peek($7100+ee1*19+ee2+38)
      if ee3=ee4 then:putarray(ee2+0,ee1+2,19,$7100,(ee3+1) mod 10):end if
      next:next
  next

'-----
'- walls (fix needed)
seed=smsrnd(seed):ee5=seed mod 8:ypos=ee5+1:yposo=ypos
seed=smsrnd(seed):ee5=seed mod 8:yposf=ee5+1

for ee1=0 to 18
  putarray(ee1,0,19,$7100,254)
  putarray(ee1,9,19,$7100,254)
  next

ee4=getarray(18,yposf,19,$7100)
for ee1=0 to 8
  putarray(0,ee1,19,$7100,254)
  putarray(18,ee1,19,$7100,254)
  next
putarray(18,yposf,19,$7100,ee4)

for ee2=0 to 16 step 2
  for ee1=0 to 15:poke $7080+ee1,0:next
  for ee1=1 to 2+stage
    loopfixwalls01:
    seed=smsrnd(seed)
    ee3=(seed mod 8)+1
    if peek($7080+ee3)<>0 then:
      goto loopfixwalls01:end if
    poke $7080+ee3,1
    next
  for ee1=0 to 8
    if peek($7080+ee1)<>0 then:
      putarray(ee2,ee1,19,$7100,254)
      end if
    next:next

'-------------------------------------------------------------------------------
'- counter 

smsfilvrm(6144,128+16,768)
for ee1=0 to 3
  for ee0=0 to 7
    bintiles(12,4+ee0,peek(@charset01+384+ee0  +((3-ee1)*8)  ),128+16,128+24)
    next
  for ee0=0 to 7
    bintiles(12,12+ee0,peek(@charset01+384+1024+ee0  +((3-ee1)*8)  ),128+16,128+24)
    next
  smswaitvbl(50)
  next

'-------------------------------------------------------------------------------
'- display

smsfilvrm(6144,128+16,768)

for ee1=0 to 9
  for ee2=0 to 18
    eee=getarray(ee2,ee1,19,$7100)
    nops()
    putchar2x1(ee2+2,(ee1+0)*2,48+eee)
    nops()
    if eee>10 then:
      nops()
      filltile(ee2+2,(ee1+0)*2,1,2,128+24-8)
      nops()
      end if
    next:next

print2x1(11,20,@textsctb01,2)
print2x1(16,20,@textsctb01+2,2)
print2x1(21,20,@textsctb01+4,2)
print2x1(24,20,@textsctb01+6,2)
print2x1(27,20,@textsctb01+8,2)

putchar2x1(28,22,48+(stage mod 10))

printdec2x2d4(11,22,score)
printdec2x2d4(16,22,hiscore)

filltile(0,(yposo)*2,2,2,128+24)
xposo=-1:xpos=0:kprs=0
tmcntr=0:kpram=0

'-------------------------------------------------------------------------------
'- stage loop

do
'invjoypad=(15-(cvjoypad1b() band 15)) bor (15-(cvjoypad2b() band 15))
invjoypad=15-((cvjoypad1b() band cvjoypad2b()) band 15)

arrvl=getarray(xpos+1,ypos,19,$7100)
if arrvl+48=peek(@numpad01+invjoypad) and kprs=0 then:
  kprs=1:xposo=xpos:yposo=ypos:pldirct=0
  smoothspritemove((2+xpos)*8,(ypos)*16-1,3,pldirct)
  xpos=xpos+1:kpram=kpram+1
  end if

arrvl=getarray(xpos-1,ypos,19,$7100)
if arrvl+48=peek(@numpad01+invjoypad) and kprs=0 then:
  kprs=1:xposo=xpos:yposo=ypos:pldirct=1
  smoothspritemove((2+xpos)*8,(ypos)*16-1,7,pldirct)
  xpos=xpos-1:kpram=kpram+1
  end if

arrvl=getarray(xpos,ypos+1,19,$7100)
if arrvl+48=peek(@numpad01+invjoypad) and kprs=0 then:
  kprs=1:xposo=xpos:yposo=ypos
  smoothspritemove((2+xpos)*8,(ypos)*16-1,5,pldirct)
  ypos=ypos+1:kpram=kpram+1
  end if

arrvl=getarray(xpos,ypos-1,19,$7100)
if arrvl+48=peek(@numpad01+invjoypad) and kprs=0 then:
  kprs=1:xposo=xpos:yposo=ypos
  smoothspritemove((2+xpos)*8,(ypos)*16-1,1,pldirct)
  ypos=ypos-1:kpram=kpram+1
  end if

'if invjoypad=0 or cvjoypad1a=15 then:
if invjoypad=0 then:
  kprs=0
  end if

'-----
'-debug
if debug<>0 then
arrvl=getarray(xpos,ypos,19,$7100)
putchar2x1(27,4,48+arrvl)
putchar2x1(30,6,peek(@numpad01+invjoypad))
end if
'-----

sg1000putsprite(0,(2+xpos)*8,(ypos)*16-1,(pldirct*16),3)
nops()
putchar2x1(2+xpos,ypos*2,32)
nops()
putarray(xpos,ypos,19,$7100,254)
nops()
filltile(2+xposo,yposo*2,1,2,128+24)
nops()

tmcntrs=int(tmcntr/50)

if tmcntrs>59 then:
  goto endgm01
  end if

printdec2x2d2(21,22,tmcntrs)
printdec2x2d2(24,22,kpram)

smswaitvbl(1)
tmcntr=tmcntr+1

'-------------------------------------------------------------------------------
'- stage loop end
if xpos>17 then
  goto endlp01:end if
loop
endlp01:

sg1000putsprite(0,0,192,0,3)
smsfilvrm(6144,128+16,768)

score=score+(60-tmcntrs)+(100-kpram)
seed=seed+score
seed=seed+tmcntr
seed=seed+tmcntrs

'- Remaining seconds:xx-xx=xx
print2x1(1,9,@text01a,@text01b-@text01a)
print2x1(11,9,@text01b,@text01c-@text01b)
printdec2x2d2(22,9,tmcntrs)
printdec2x2d2(25,9,60-tmcntrs)

'- Remaining keypresses:xxx-xx=xx
print2x1(1,11,@text01a,@text01b-@text01a)
print2x1(11,11,@text01c,@text01d-@text01c)
printdec2x2d2(26,11,kpram)
printdec2x2d2(29,11,100-kpram)

'- Score for maze x:xxxx
print2x1(1,13,@text01d,@text01e-@text01d)
printdec2x2d4(18,13,(60-tmcntrs)+(100-kpram))
putchar2x1(16,13,48+(stage mod 10))

'- Total score
print2x1(1,16,@text01e,@text01f-@text01e)
print2x1(7,16,@text01g,@text01h-@text01g)
printdec2x2d4(13,16,score)

'- Best score
print2x1(1,18,@text01f,@text01g-@text01f)
print2x1(6,18,@text01g,@text01h-@text01g)
printdec2x2d4(12,18,hiscore)

'- push any key
print2x1(1,21,@text02g+1,@text02h-@text02g-1)

stage=stage+1
smswaitvbl(50)

do
tmcntr=tmcntr+1
invjoypad=15-((cvjoypad1b() band cvjoypad2b()) band 15)
if invjoypad=0 then:
  else
    goto leavetitle02
  end if
loop

leavetitle02:
seed=seed+tmcntr

if stage>5 then:
  hiscore=score
  goto start01
  end if

'-------------------------------------------------------------------------------
'- game loop end
loop

endgm01:
goto start01

'-------------------------------------------------------------------------------
'- defb

do:loop

numpad01:
asm
defb "?61390*?2#7?548?"
end asm

tilebrick01:
asm
  defb %00000001
  defb %00000001
  defb %00000001
  defb %11111111
  defb %00010000
  defb %00010000
  defb %00010000
  defb %11111111
  end asm

textsctb01:
asm
  defb "ScHsTmKpMz"
  end asm

text01:
text01a:
asm
  defb "Remaining "
  end asm
text01b:
asm
  defb "seconds:60-__=__ "
  end asm
text01c:
asm
  defb "keypresses:100-__=__ "
  end asm
text01d:
asm
  defb "Score for maze _:____ "
  end asm
text01e:
asm
  defb "Total "
  end asm
text01f:
asm
  defb "Best "
  end asm
text01g:
asm
  defb "score:____ "
  end asm
text01h:

textsctb02:
text02a:
asm
  defb " Numeric Maze "
  end asm
text02b:
asm
  defb " Original "
  end asm
text02c:
asm
  defb " Colecovision "
  end asm
text02d:
asm
  defb " version "
  end asm
text02e:
asm
  defb " Mircea Petza, 2008 "
  end asm
text02f:
asm
  defb " Paulo Silva, 2017 "
  end asm
text02g:
asm
  defb " Push any key "
  end asm
text02h:

'-------------------------------------------------------------------------------

