/programs/games/codemaster/A.INC |
---|
0,0 → 1,47 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; ************** STAR^2 SOFTWARE ***************** |
; ???????????????????????????????????????????????? |
; true portability: windows + kolibri |
; define cpu intel windows |
define cpu intel kolibri |
; define cpu arm mobile |
; current directory. optional '/usbhd0/1' |
; prefix to assemble+run from SD in kolibri |
CD fix '' |
; CD fix '/usbhd0/1' |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MAIN.ICON fix '' |
SCREEN.W = WINDOW.W ; 1024 |
SCREEN.H = WINDOW.H ; 768-32 |
SCREEN.BPP = 32 |
SCREEN.PI = SCREEN.W*(SCREEN.BPP/8) |
match x =windows, cpu { |
format PE GUI 4.0 |
entry !main |
stack 8*KB |
heap 16*KB |
include CD#'/include/a.inc' |
WINDOW.X=0 |
WINDOW.Y=0 |
} |
match x =kolibri, cpu { |
format binary as "" |
use32 |
org 0 |
db 'MENUET01' |
dd 1, !main, end.code,\ |
4*MB, 32*KB, 0, 0 |
postpone \{ end.code: \} |
include CD#'/include/a.inc' |
WINDOW.X=(1024/2)-(WINDOW.W/2) |
WINDOW.Y=(768/2)-(WINDOW.H/2) |
} |
/programs/games/codemaster/BINARY_MASTER.ASM |
---|
0,0 → 1,299 |
; BINARY MASTER |
WINDOW.W=360 |
WINDOW.H=492 |
include 'a.inc' |
text t(256), title.t='Binary Master: %hh' |
text help.t=+\ |
'Fun Game for Programmers.' RET\ |
'Click BITs. Count in binary.' RET\ |
'Match the decimal number' RET\ |
'in the red box to make rows' RET\ |
'disappear. Press any key.' RET\ |
'r=Reset. p=Pause. Esc=exit' |
text pause.t=+\ |
'Paused. Press p to continue' RET\ |
'or r=Reset. Esc=exit' |
text game.over.t=+\ |
'Game over. Score: %hh.' RET\ |
'Press any key' |
align |
integer scene, score |
numeric SCENE.*, TITLE, PLAY,\ |
PAUSE, GAME.OVER |
numeric EASY=5000, NORMAL=4000, HARD=2000 |
BOX board, my.box |
integer my.n, red.n, magic.n=10101101b |
integer cbit.x, cbit.y, bits.h |
numeric BIT.*, W=32, H=48 |
text my.numbers(8+4), red.numbers(8+4) |
FONT main.font='font' |
IMAGE bits.i='bits', bit1.i='1',\ |
bit0.i='0', close.i='x' |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
function random.byte |
locals n |
.r: |
random 3 |
if r0<2 |
random 16 |
else.if r0=2 |
random 128 |
else.if r0=3 |
random 255 |
end |
. n=r0 |
text.find red.numbers, n |
if true, go .r, end |
. r0=n |
if false, r0++, end |
endf |
function reset.game |
locals n, p |
. score=0, bits.h=1 |
memory.zero my.numbers, 12 |
memory.zero red.numbers, 12 |
. n=8, p=red.numbers |
loop n |
random.byte |
. r1=p, *r1++=r0, p=r1 |
endl |
set.box board, 4, 70, BIT.W*8, BIT.H*8 |
. scene=SCENE.TITLE |
endf |
function on.create |
set.font main.font |
set.timer NORMAL |
reset.game |
endf |
function remove.byte, t, i |
locals n |
alias p=r0, q=r1, x=r2 |
if i=7, go .new, end |
. p=t, p+i, q=p, q++, x=7, x-i, n=x |
loop n, *p++=*q++, endl |
.new: |
. p=my.numbers, *(p+7)=0 |
random.byte |
. q=red.numbers, *(q+7)=r0 |
endf |
function remove.row, i |
remove.byte my.numbers, i |
remove.byte red.numbers, i |
. bits.h-- |
if bits.h<1, bits.h=1, end |
endf |
function check.numbers |
locals i |
. i=0 |
while i<8, r0=my.numbers, r0+i |
. r1=*r0, r0=red.numbers |
. r0+i, r2=*r0 |
if r1=r2, score+r1 |
remove.row i |
return 1 |
end |
. i++ |
endw |
endf 0 |
function draw.board |
locals i, n, x, y, w, h |
draw.image bits.i, 4, 35 |
draw.image bits.i, 4, 457 |
. x=0, y=0, w=32, h=48 |
while y<8, x=0 |
while x<8 |
. r0=x, r0*w, r0+board.x |
. r1=y, r1*h, r1+board.y |
set.box my.box, r0, r1, w, h |
draw.box my.box, BLACK, GRAY |
. x++ |
endw |
. r0=x, r0*w, r0+board.x |
. r1=y, r1*h, r1+board.y |
set.box my.box, r0, r1, 48, h |
draw.box.o my.box, WHITE |
. my.box.x+48 |
draw.box.o my.box, RED |
. r0=y, r1=8, r1-bits.h |
if r0>=r1 |
. r0=my.numbers, r1=y, r2=8 |
. r2-bits.h, r1-r2, r0+r1 |
. r1=*r0, my.n=r1 |
. r0=red.numbers, r1=y, r2=8 |
. r2-bits.h, r1-r2, r0+r1 |
. r1=*r0, red.n=r1 |
u2t my.n, t |
. my.box.x-40, my.box.y+11 |
draw.text t, my.box.x, my.box.y |
. my.box.x+44 |
u2t red.n, t |
draw.text t, my.box.x, my.box.y |
end |
. y++ |
endw |
endf |
function draw.bit, n, x, y |
if n |
draw.image bit1.i, x, y |
else |
draw.image bit0.i, x, y |
end |
endf |
function draw.byte, n, x, y |
locals i |
. i=8 |
loop i, r0=n, r1=i, r1--, r0>>cl, r0&1 |
draw.bit r0, x, y |
. x+BIT.W |
endl |
endf |
function draw.my.numbers |
locals i, n, y |
. i=bits.h, y=404 |
loop i, r0=my.numbers, r0+i, r0-- |
. r0=*r0, n=r0 |
draw.byte n, 4, y |
. y-BIT.H |
endl |
endf |
function draw.title.scene |
draw.text help.t, 16, 130 |
draw.byte magic.n, 50, 300 |
endf |
function draw.play.scene |
draw.board |
draw.my.numbers |
endf |
function draw.pause.scene |
draw.text pause.t, 16, 130 |
draw.byte magic.n, 50, 300 |
endf |
function draw.game.over |
print t, game.over.t, score |
draw.text t, 44, 170 |
draw.byte magic.n, 50, 300 |
endf |
function on.draw |
locals x, y, w, h |
clear.screen BLACK |
print t, title.t, score |
draw.text t, 4, 4 |
draw.image close.i, 324, 4 |
. r0=screen.w, r0-- |
. r1=screen.h, r1-- |
draw.outline 0, 0, r0, r1, GRAY |
if scene=SCENE.TITLE |
draw.title.scene |
else.if scene=SCENE.PLAY |
draw.play.scene |
else.if scene=SCENE.PAUSE |
draw.pause.scene |
else.if scene=SCENE.GAME.OVER |
draw.game.over |
end |
endf |
function on.key |
if key.event='c' |
if scene=SCENE.TITLE |
. scene=SCENE.PLAY |
go .draw |
end |
if scene=SCENE.GAME.OVER |
go .reset |
end |
if key='r' |
.reset: |
reset.game |
go .draw |
end |
if key='p' |
.pause: |
if scene=SCENE.PLAY |
. scene=SCENE.PAUSE |
else.if scene=SCENE.PAUSE |
. scene=SCENE.PLAY |
end |
go .draw |
end |
.draw: |
render |
end |
endf |
function on.mouse |
if.select board |
. r0=mouse.x, r0-WINDOW.X, r0-board.x |
. r1=BIT.W, r0/r1, cbit.x=r0 |
. r0=mouse.y, r0-WINDOW.Y, r0-board.y |
. r1=BIT.H, r0/r1, cbit.y=r0 |
if mouse.event='c' |
. r0=cbit.y, r1=8, r1-bits.h |
if r0>=r1, r0=my.numbers, r1=cbit.y |
. r2=8, r2-bits.h, r1-r2, r0+r1 |
. r3=*r0, r2=1, r1=7, r1-cbit.x |
. r2<<cl, r3><r2, *r0=r3 |
end |
end |
end |
if mouse.event='r' |
check.numbers |
go .draw |
end |
if mouse.event='c' |
. r0=&close.i.x |
if.select r0 |
exit |
end |
if scene<>SCENE.PLAY |
reset.game |
. scene=SCENE.PLAY |
end |
.draw: |
render |
end |
endf |
function on.timer |
if scene<>SCENE.PLAY |
return |
end |
if mouse.1, return, end |
if bits.h<8, bits.h++ |
else |
. scene=SCENE.GAME.OVER |
end |
render |
endf |
function on.exit |
; ... |
endf |
/programs/games/codemaster/HANG_PROGRAMMER.ASM |
---|
0,0 → 1,392 |
; HANG PROGRAMMER |
WINDOW.W=720 |
WINDOW.H=512 |
include 'a.inc' |
include 'include/words.txt' |
text title.t(32)='Hang Programmer' |
text t(256), t2(256) |
integer scene |
numeric SCENE.*, TITLE, PLAY, GAME.OVER |
integer guesses, word.index |
BOX my.box |
text word.t(64), used.letters(16) |
align |
IMAGE8 \ |
board.i='board', logo.i='logo',\ |
stand1.i='stand1', stand2.i='stand2',\ |
head.i='head', body.i='body',\ |
arm1.i='arm1', arm2.i='arm2',\ |
leg1.i='leg1', leg2.i='leg2',\ |
smile.i='smile', money.i='money',\ |
prize.i='1000' |
IMAGE close.i='x' |
text abc='ABCDEFGHIJKLM', xyz='NOPQRSTUVWXYZ' |
text help.t='CLICK TO START',\ |
winner.t='WINNER', looser.t='LOOSER' |
text example.t='DYNAMIC BINARY TRANSLATION' |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
function reset.game |
. guesses=0 |
text.zero used.letters |
text.zero word.t |
. r0=word.index, r0*4, r0+words.pa |
. (u32) r0=*r0 |
text.copy word.t, r0 |
. word.index++ |
if word.index>=(N.WORDS-1) |
. word.index=0 |
end |
endf |
; exchange pointer array elements. |
; words.pa[a] and [b] |
function exchange.words, a, b |
alias pa=r0, i=r0, p=r1, q=r2, x=r3 |
. pa=words.pa |
. p=a, p*4, p+pa, q=b, q*4, q+pa |
. (u32) i=*p, (u32) x=*q |
. (u32) *p=x, (u32) *q=i |
endf |
; do this once when game begins. |
; initialize pointer array to words[0-n] |
; then randomize indices |
function initialize |
locals i, n, j |
alias p=r0, x=r1 |
. p=words.pa, i=0, n=N.WORDS |
loop n, x=i, (u32) x=*(words.ta+r1*4) |
. (u32) *p++=x, i++ |
endl |
. i=N.WORDS |
loop i |
get j=random (N.WORDS-1) |
exchange.words i, j |
endl |
. word.index=0 ; random (N.WORDS-1) |
endf |
; is winner? if all characters in |
; word.t have been used. return |
; winner.t/looser.t |
function is.winner |
locals i, q, n, win |
alias p=r0, c=r1 |
. q=word.t |
get n=text.n q |
. win=1 |
loop n, p=q, c=*p++ |
if c<>' ' |
text.find used.letters, c |
if false |
. win=0, break |
end |
end |
. q++ |
endl |
if win, r0=winner.t |
else, r0=looser.t, end |
endf |
function on.create |
initialize |
reset.game |
endf |
function insert.c, c |
if c>='a', c-32, end |
if c<'A', return, end |
if c>'Z', return, end |
text.find used.letters, c |
if true, return, end |
text.attach.c used.letters, c |
is.winner |
if r0=winner.t |
go .reset |
end |
text.find word.t, c |
if true, return, end |
. guesses++ |
if guesses=6 |
.reset: . scene=SCENE.GAME.OVER |
end |
endf |
; special "my" font |
align |
alphabet.p: dd \ |
a.i, b.i, c.i, d.i, e.i, f.i, g.i, h.i, i.i,\ |
j.i, k.i, l.i, m.i, n.i, o.i, p.i, q.i, r.i,\ |
s.i, t.i, u.i, v.i, w.i, x.i, y.i, z.i |
irps _,\ |
a b c d e f g h i j k l m \ |
n o p q r s t u v w x y z { |
IMAGE8 _#.i='a/'#`_ |
} |
function index.my.c, c |
. r0=c, r0-'A', r0*4, r0+alphabet.p |
. (u32) r0=*r0 |
endf |
function get.my.cw, c |
if c=' ', return 0, end |
index.my.c c |
. (u32) r0=*(r0+?image.w) |
endf |
function get.my.tw, t |
locals n, w |
alias p=r0, c=r1 |
get n=text.n t |
. w=0 |
loop n, p=t, c=*p |
get.my.cw c |
. w+r0, t++ |
endl |
endf w |
function draw.my.c, c, x, y, co |
locals im, w |
if c=' ', return, end |
get im=index.my.c c |
. (u32) r1=*(r0+?image.w), w=r1 |
draw.image.v8 im, x, y, co |
endf w |
function draw.my.text, t, x, y |
locals p, n |
get n=text.n t |
. p=t |
loop n, r0=p, r0=*r0 |
draw.my.c r0, x, y, WHITE |
. x+r0, x+4, p++ |
endl |
endf |
function draw.my.word, t, x, y |
locals p, n, w, c, co |
get n=text.n t |
. p=t |
loop n, r0=p, r0=*r0, c=r0 |
get w=get.my.cw c |
text.find used.letters, c |
if true |
. r0=x, r0+18, r1=w, r1/2, r0-r1 |
draw.my.c c, r0, y, WHITE |
end |
. r0=x, r0+2, r1=y, r1+48 |
draw.box r0, r1, 32, 3, WHITE |
. r0=36, x+r0, p++ |
endl |
endf |
function draw.message |
locals n, x, y, w |
get n=text.count.w word.t |
if n=0, n=1, end |
set.source word.t |
set.token t |
. x=250, y=80 |
loop n |
skip.space |
copy.until C.SPACE |
set.box my.box, 250, 65, 390, 220 |
text.n t |
. r0*36, w=r0, r0=my.box.x, r0+195 |
. r1=w, r1/2, r0-r1 |
draw.my.word t, r0, y |
. y+70 |
endl |
endf |
function draw.letters, t, x, y |
locals n, p, c, co |
get n=text.n t |
. p=t |
loop n, r0=p, r0=*r0, c=r0 |
index.my.c c |
. r0+?image.box |
memory.copy my.box, r0, 16 |
. my.box.x=x, my.box.y=y |
if.select my.box |
if mouse.1 |
insert.c c |
end |
end |
. co=WHITE |
text.find used.letters, c |
if true, co=409040h, end |
draw.my.c c, x, y, co |
. r0+4, x+r0, p++ |
endl |
endf |
function draw.alphabet |
draw.letters abc, 255, 308 |
draw.letters xyz, 248, 370 |
endf |
function draw.man |
locals x, y |
. x=40, y=62 |
. alpha.bias=A.DARK |
draw.image.v.8 stand1.i, x, y, WHITE |
. r0=x, r0+27 |
draw.image.v.8 stand2.i, r0, y, WHITE |
. alpha.bias=A.DARKER |
if guesses>0 |
. r0=x, r0+80, r1=y, r1+40 |
draw.image.v.8 head.i, r0, r1, WHITE |
end |
if guesses>1 |
. r0=x, r0+95, r1=y, r1+150 |
draw.image.v.8 body.i, r0, r1, WHITE |
end |
if guesses>2 |
. r0=x, r0+70, r1=y, r1+150 |
draw.image.v.8 arm1.i, r0, r1, WHITE |
end |
if guesses>3 |
. r0=x, r0+143, r1=y, r1+150 |
draw.image.v.8 arm2.i, r0, r1, WHITE |
end |
if guesses>4 |
. r0=x, r0+87, r1=y, r1+228 |
draw.image.v.8 leg1.i, r0, r1, WHITE |
end |
if guesses>5 |
. r0=x, r0+118, r1=y, r1+228 |
draw.image.v.8 leg2.i, r0, r1, WHITE |
end |
. alpha.bias=0 |
endf |
function draw.hang.man |
. guesses=6 |
draw.man |
. guesses=0 |
endf |
function draw.winner |
locals x, y |
. alpha.bias=A.DARKER |
. x=40, y=62 |
. r0=x, r0+80, r1=y, r1+40 |
draw.image.v.8 head.i, r0, r1, WHITE |
. r0=x, r0+95, r1=y, r1+150 |
draw.image.v.8 body.i, r0, r1, WHITE |
. r0=x, r0+67, r1=y, r1+87 |
draw.image.viy.8 arm1.i, r0, r1, WHITE |
. r0=x, r0+147, r1=y, r1+87 |
draw.image.viy.8 arm2.i, r0, r1, WHITE |
. r0=x, r0+87, r1=y, r1+228 |
draw.image.v.8 leg1.i, r0, r1, WHITE |
. r0=x, r0+118, r1=y, r1+228 |
draw.image.v.8 leg2.i, r0, r1, WHITE |
. alpha.bias=A.LIGHT |
draw.image.v.8 smile.i, 547, 307, WHITE |
draw.image.v.8 smile.i, 310, 307, WHITE |
. alpha.bias=A.DARK |
draw.image.v.8 money.i, 547, 342, 0DDFFDDh |
draw.image.v.8 prize.i, 367, 377, WHITE |
. alpha.bias=0 |
endf |
function draw.title.scene |
draw.my.text help.t, 237, 100 |
draw.hang.man |
endf |
function draw.play.scene |
draw.message |
draw.alphabet |
draw.man |
endf |
function draw.game.over |
locals p |
get p=is.winner |
draw.my.text p, 362, 308 |
draw.message |
if p=winner.t |
draw.winner |
else |
draw.hang.man |
end |
endf |
function on.draw |
clear.screen 283D25h |
draw.image.8 board.i, 0, 0 |
. alpha.bias=A.DARKER |
draw.image.v.8 logo.i, 240, 32, WHITE |
. alpha.bias=0 |
if scene=SCENE.TITLE |
draw.title.scene |
else.if scene=SCENE.PLAY |
draw.play.scene |
else.if scene=SCENE.GAME.OVER |
draw.game.over |
end |
draw.image close.i, 663, 28 |
endf |
function on.key |
if key.event='k' |
if scene=SCENE.PLAY |
insert.c key |
else.if scene=SCENE.TITLE |
reset.game |
. scene=SCENE.PLAY |
else.if scene=SCENE.GAME.OVER |
reset.game |
. scene=SCENE.TITLE |
end |
render |
end |
endf |
function on.mouse |
if mouse.event='c' |
. r0=&close.i.x |
if.select r0 |
exit |
end |
if scene=SCENE.TITLE |
reset.game |
. scene=SCENE.PLAY |
else.if scene=SCENE.GAME.OVER |
reset.game |
. scene=SCENE.TITLE |
end |
render |
end |
endf |
function on.timer |
; ... |
endf |
function on.exit |
; ... |
endf |
/programs/games/codemaster/INCLUDE/A.INC |
---|
0,0 → 1,26 |
match =intel x, cpu { |
include 'language.inc' |
} |
include 'memory.inc' |
include 'text.inc' |
match x =windows, cpu |
{ include 'draw.inc' } |
match x =kolibri, cpu |
{ include 'drawk.inc' } |
match x =windows, cpu |
{ include 'image.inc' } |
match x =kolibri, cpu |
{ include 'imagek.inc' } |
include 'font.inc' |
match x =windows, cpu |
{ include 'system.inc' } |
match x =kolibri, cpu |
{ include 'systemk.inc' } |
/programs/games/codemaster/INCLUDE/BOX.INC |
---|
0,0 → 1,218 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ??????????????????? BOX.INC ???????????????????? |
screen.w equ [!screen.w] ; forward reference |
screen.h equ [!screen.h] ; restore at end |
macro BOX [p] { |
forward p: integer p#.x, p#.y, p#.w, p#.h |
} |
;;;;;;;;;;;;;;;;;; VISIBILITY ;;;;;;;;;;;;;;;;;;;; |
; is visible or partially? return 0 if |
; completely invisible |
function visible, x, y, w, h |
if w<=0, go .0, end |
if h<=0, go .0, end |
. r0=x, r1=y |
if r0>=screen.w, go .0, end |
if r1>=screen.h, go .0, end |
. r0+w, r1+h |
if r0<0, go .0, end |
if r1<0, go .0, end |
return 1 |
.0: |
endf 0 |
;;;;;;;;;;;;;;; POINT INSIDE BOX? ;;;;;;;;;;;;;;;; |
; x>=bx and x<bx+bw and y>=by and y<by+bh |
function point.inside, b, x, y |
locals b.x, b.y, b.w, b.h |
. r0=b,\ |
b.x=[?box.x+r0], b.y=[?box.y+r0],\ |
b.w=[?box.w+r0], b.h=[?box.h+r0],\ |
r1=x, r2=b.x |
cmp r1, r2 |
jl .r0 |
add r2, b.w |
cmp r1, r2 |
jge .r0 |
. r1=y, r2=b.y |
cmp r1, r2 |
jl .r0 |
add r2, b.h |
cmp r1, r2 |
jge .r0 |
return 1 |
.r0: . r0=0 |
endf |
;;;;;;;;;;;;;;;;;;;;;; CLIP ;;;;;;;;;;;;;;;;;;;;;; |
; "clipping"; to exclude invisible sections of |
; imagery before drawing |
; clip.pixel x, y. if invisible, return 0 |
function clip.pixel, x, y |
. r0=x, r1=y |
if r0<0, go .0, end |
if r0>=screen.w, go .0, end |
if r1<0, go .0, end |
if r1>=screen.h, go .0, end |
return 1 |
.0: |
endf 0 |
; 2-DO: convert to ABAKIS... |
; clip.line o, &x, &y, &n. return 0 if |
; completely invisible or adjust x/y/n |
; if partially in/visible. o/rientation= |
; 'h'/'v'. n=w/h. parameters sent by |
; reference |
function clip.line, o, x, y, n |
push r6 r7 r3 |
. r6=x, r7=y, r3=n,\ |
r0=[r6], r2=[r7], r1=[r3] |
; if invisible, return 0 |
cmp r0, screen.w ; x>=screen.w? |
jge .0 |
cmp r2, screen.h ; y>=screen.h? |
jge .0 |
cmp r1, 0 ; w/h<=0? |
jle .0 |
cmp o, 0 ; orientation? |
jne .vertical |
.horizontal: |
cmp r2, 0 ; y<0? |
jl .0 |
cmp r2, screen.h ; y>=screen.h? |
jge .0 |
. r2=r0, r2+r1 ; x+w<0? |
cmp r2, 0 |
jl .0 |
if r0<0 ; if x<0 |
. r0+r1,\ ; { w=x+w, x=0 } |
[r3]=r0,\ |
dword [r6]=0 |
end |
cmp r2, screen.w ; if x+w>=screen.w |
jl @f ; { w=screen.w-x } |
. r0=screen.w,\ |
r0-[r6], [r3]=r0 |
@@: |
jmp .yes |
.vertical: |
cmp r0, 0 ; x<0? |
jl .0 |
cmp r0, screen.w ; x>=screen.w? |
jge .0 |
. r1=r2,\ |
r1+[r3] ; y+h<0? |
cmp r1, 0 |
jl .0 |
if r2<0 ; if y<0 |
. [r3]=r1,\ ; { h=y+h, y=0 } |
dword [r7]=0 |
end |
cmp r1, screen.h ; if y+h>=screen.h |
jl .yes ; { h=screen.h-y } |
. r0=screen.h,\ |
r0-[r7], [r3]=r0 |
.yes: . r0=YES |
jmp .e |
.0: . r0=NO |
.e: |
pop r3 r7 r6 |
endf |
; clip.scanline &s, &x, &y, &w does the same |
; as clip.line but sets the s/tart offset of |
; pixels and adjusts w correctly. this only |
; applies to scanlines, not one-color lines |
function clip.scanline, s, x, y, w |
push r3 |
. r3=s,\ |
dword [r3]=0,\ ; offset=0 initially |
r0=x, r0=[r0] |
cmp r0, screen.w ; x>=screen.w? |
jge .0 |
. r2=y, r2=[r2] |
cmp r2, screen.h ; y>=screen.h? |
jge .0 |
cmp r2, 0 ; y<0? |
jl .0 |
cmp r2, screen.h ; y>=screen.h? |
jge .0 |
. r1=w, r1=[r1],\ |
r3=r0, r3+r1 ; x+w<0? |
cmp r3, 0 |
jl .0 |
cmp r3, screen.w ; if x+w>=screen.w |
jl @f ; w=screen.w-x |
. r1=screen.w,\ |
r1-r0, r3=w,\ |
[r3]=r1 |
@@: |
cmp r0, 0 ; if x<0, clip |
jg .e |
. r2=r0, -r2, r2*4 ; index=-x * scale |
. r3=s, [r3]=r2,\ |
r1=w, [r1]+r0,\ ; w+=x |
r3=x, dword [r3]=0 ; x=0 |
. r0=YES |
jmp .e |
.0: . r0=NO |
.e: |
pop r3 |
endf |
;;;;;;;;;;;;;;;;;;;;;;; BOX ;;;;;;;;;;;;;;;;;;;;;; |
; BOX structure... |
virtual at 0 |
?box: |
.x dd 0 |
.y dd 0 |
.w dd 0 |
.h dd 0 |
END virtual |
align |
box: |
integer .x, .y, .w, .h |
macro set.box box, x, y, w, h { |
. box#.x=x, box#.y=y,\ |
box#.w=w, box#.h=h |
} |
function move.box.right, b, n |
. r0=b, r1=n, r0+?box.x, [r0]+r1 |
endf |
function move.box.down, b, n |
. r0=b, r1=n, r0+?box.y, [r0]+r1 |
endf |
function move.box.r, b |
. r0=b, r1=[?box.w+r0], r0+?box.x, [r0]+r1 |
endf |
function move.box.d, b |
. r0=b, r1=[?box.h+r0], r0+?box.y, [r0]+r1 |
endf |
restore screen.w, screen.h |
/programs/games/codemaster/INCLUDE/COLOR.INC |
---|
0,0 → 1,227 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ?????????????????? COLOR.INC ??????????????????? |
COLOR fix integer |
PIXEL fix integer |
; rgb r, g, b |
; get.rgb c, &r, &g, &b |
; set.rgb &c, r, g, b |
; mix a, b, n ; alpha combination |
; lightness c, n ; adjust light/darkness. n=+/- |
; colorize a, b, n ; in/decrease r/g/b |
; grayscale c ; convert to grayscale |
; inversion c ; invert |
; channelize a, b ; split r/g/b channel |
; PAL1 = I (2) |
; PAL2 = II (4) |
; PAL4 = IIII (16) |
; PAL8 = IIIIIIII (256) |
; PAL10 = IIIIIIIIII (1K, 1024) |
; PAL12 = IIIIIIIIIIII (4K, 4096) |
; RGB15 = X.RRRRR.GGGGG.BBBBB (32768, 32K) |
; RGB16 = RRRRR.GGGGGG.BBBBB (65535, 64K) |
; RGB24 = R8.G8.B8 (16777216, 16M) |
; RGB32 = A8.R8.G8.B8 (same with alpha) |
; "standard" colors |
numeric BLACK=0, WHITE=0FFFFFFh,\ |
RED=0FF0000h, GREEN=0FF00h, BLUE=0FFh,\ |
CYAN=BLUE+GREEN, MAGENTA=RED+BLUE,\ |
YELLOW=RED+GREEN, GRAY32=202020h,\ |
GRAY64=404040h, GRAY128=808080h,\ |
GRAY192=0C0C0C0h, GRAY224=0E0E0E0h,\ |
GRAY=808080h, GRAY25=404040h,\ |
GRAY50=GRAY, GRAY75=0C0C0C0h |
; personally selected "cool colors". includes |
; nature colors for custom brushes/textures - |
; grass, dirt, etc |
numeric \ |
RED.CHERRY=720E21h, FIRE.RED=821100h,\ |
RED.ROSE=7B0024h, DARK.RED=470707h,\ |
POWER.BLUE=0B008Ah, ROYAL.BLUE=140357h,\ |
BEACH.BLUE=0362C1h, DARK.BLUE=070720h,\ |
ICE.BLUE=8ACAE2h, SKY.BLUE=0A3A3F9h,\ |
CLOUD.BLUE=11A3F5h, BABY.BLUE=4F77FFh,\ |
LILAC=0DA4FE7h, PURPLE=700E7Fh,\ |
VIOLET=08C047Ah, DARK.VIOLET=2D0327h,\ |
LIME.GREEN=8CE007h, SEA.GREEN=72CC90h,\ |
LEAF.GREEN=7EBB1Dh, GRASS.GREEN=507B11h,\ |
DARK.GREEN=0B1F0Fh, EMERALD.GREEN=1C3E14h,\ |
PINK=0FF67A0h, PASTEL.PINK=0F7A7CFh,\ |
ROSE.PINK=0FB57A0h, PINK.FLESH=0FBD7BDh,\ |
FLESH=0FCEEDEh, MEDIUM.FLESH=0EF9F5Dh,\ |
DARK.FLESH=0E87D2Eh, LIGHT.BROWN=0C77237h,\ |
DARK.BROWN=4D2207h, ORANGE.BROWN=0B04700h,\ |
RED.BROWN=782712h, SAND=0D1A877h,\ |
COOL.GRAY=837B9Bh, LILAC.GRAY=0E1ABFFh,\ |
METAL.GRAY=0AEBEBEh, LIGHT.GRAY=0E7E7E7h |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; construct RGB 24/32BPP. assumes 0-255 |
function rgb, r, g, b |
. r0=r, r0<<16, r1=g, r1<<8,\ |
r0|r1, r2=b, r0|r2 |
endf |
macro rgbm r, g, b { |
. r0=r, r0<<16, r1=g, r1<<8,\ |
r0|r1, r0|b |
} |
; with truncation. ensure 0-255 |
function rgbc, r, g, b |
. r0=r, r0&0FFh, r0<<16,\ |
r1=g, r1&0FFh, r1<<8, r0|r1,\ |
r2=b, r2&0FFh, r0|r2 |
endf |
; extract rgb components from color |
; parameters: c, &r, &g, &b. addresses |
function get.rgb, c, r, g, b |
. r0=c,\ |
r1=r0, r1>>16, r1&0FFh, r2=r, [r2]=r1,\ |
r1=r0, r1>>8, r1&0FFh, r2=g, [r2]=r1,\ |
r1=r0, r1&0FFh, r2=b, [r2]=r1 |
endf |
; set rgb of color. parameters: &c, r, g, b. |
; c is address |
function set.rgb, c, r, g, b |
rgbm r, g, b |
. r1=c, [r1]=r0 |
endf |
;;;;;;;;;;;;;;;;;;; CLIP RGB ;;;;;;;;;;;;;;;;;;;;; |
; clip RGB components, 0-255. if c<min, c=min. |
; if c>max, c=max. all parameters are address |
function clip.c, c |
. r0=c, r0=[r0] |
if r0<0, r0=0 |
else.if r0>255 |
r0=255 |
end |
. r2=c, [r2]=r0 |
endf |
function clip.rgb, r, g, b |
clip.c r |
clip.c g |
clip.c b |
endf |
;;;;;;;;;;;;;;;;;;;;; ALPHA ;;;;;;;;;;;;;;;;;;;;;; |
; mix a, b, n - alpha blend/combination. |
; n=0-255. (((s-d)*n)/256)+d |
function mix, a, b, n |
locals sr, sg, sb, dr, dg, db |
. r0=a, r2=b,\ |
r1=r0, r1>>16, r1&0FFh, sr=r1,\ |
r1=r0, r1>>8, r1&0FFh, sg=r1,\ |
r1=r0, r1&0FFh, sb=r1,\ |
r1=r2, r1>>16, r1&0FFh, dr=r1,\ |
r1=r2, r1>>8, r1&0FFh, dg=r1,\ |
r1=r2, r1&0FFh, db=r1,\ |
r0=sr, r0-dr, r0*n, r0>>8, r0+dr,\ |
r1=sg, r1-dg, r1*n, r1>>8, r1+dg,\ |
r2=sb, r2-db, r2*n, r2>>8, r2+db,\ |
r0<<16, r1<<8, r0|r1, r0|r2 |
endf |
; mix25/50/75 a, b, n - much faster |
; if alpha is constant 25%/50%/75% |
; ((a&0FEFEFEh)>>1)|((b&0FEFEFEh)>>1) |
macro mix50 a, b { |
. r0=a, r2=b, r1=0FEFEFEh,\ |
r0&r1, r0>>1, r2&r1, r2>>1, r0|r2 |
} |
function mix25, a, b |
mix50 a, b |
mix50 r0, b |
endf |
function mix75, a, b |
mix50 a, b |
mix50 a, r0 |
endf |
;;;;;;;;;;;;;;;; COLOR OPERATIONS ;;;;;;;;;;;;;;;; |
macro operation name, [ps] { |
common |
function name, ps |
locals r, g, b |
. r0=&r, r1=&g, r2=&b |
get.rgb c, r0, r1, r2 |
; ... |
} |
macro endo { |
; ... |
. r0=&r, r1=&g, r2=&b |
clip.rgb r0, r1, r2 |
rgb r, g, b |
endf |
} |
; adjust light/darkness. n=+/- |
operation lightness, c, n |
. r1=n, r+r1, g+r1, b+r1 |
endo |
; in/decrease r/g/b |
operation colorize, c, x, n |
. r1=n |
if x=RED, r+r1, g-r1, b-r1 |
else.if x=GREEN, r-r1, g+r1, b-r1 |
else.if x=BLUE, r-r1, g-r1, b+r1 |
end |
endo |
; convert to grayscale. algorithm: |
; g=(r+g+b)/3, rgb(g,g,g). no "endo" |
; after. r0=return. note: n/3 = |
; (n*155h)>>10 |
operation grayscale, c |
. r0=r, r0+g, r0+b, r0*155h,\ |
r0>>>10, r1=r0, r1<<8, r0|r1,\ |
r1<<8, r0|r1 |
endf |
; invert color: c=255-c |
operation inversion, c |
. \ |
r1=255, r1-r, r0=&r, [r0]=r1,\ |
r1=255, r1-g, r0=&g, [r0]=r1,\ |
r1=255, r1-b, r0=&b, [r0]=r1 |
endo |
; split rgb channel: a=&~b. for 3D |
; anaglyph images with R/B glasses |
function channelize, a, b |
. r0=a, r1=b, not r1, r0&r1 |
endf |
purge operation, endo |
/programs/games/codemaster/INCLUDE/DRAW.INC |
---|
0,0 → 1,385 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ?????????????????? DRAW.INC ???????????????????? |
; fast portable graphics |
include 'color.inc' |
include 'box.inc' |
;;;;;;;;;;;;;;;;;;;;; SCREEN ;;;;;;;;;;;;;;;;;;;;; |
align |
void vga.p |
integer screen.x, screen.y,\ |
screen.w, screen.h, screen.n,\ |
screen.bpp, screen.size,\ |
screen.pw, screen.pitch |
void palette.p |
BOX g.box |
function set.screen, w, h, bpp |
alias n=r0, pw=r1 |
. screen.w=w, screen.h=h ; size |
. n=w, n*h, screen.n=n ; # pixels |
. pw=bpp, pw/8 ; pixel width |
. screen.pw=pw, n*pw ; screen size |
. screen.size=n ; in bytes |
. n=w, n*pw ; screen pitch |
. screen.pitch=n ; w in bytes |
. screen.bpp=bpp ; bits per pixel |
endf |
;;;;;;;;;;;;;;;;;;;; DRAWING ;;;;;;;;;;;;;;;;;;;;; |
; erase screen with color |
function clear.screen, c |
alias p=r0, n=r1, z=r2 |
. p=vga.p, n=screen.n, z=c |
loop n, (u32) *p++=z, endl |
endf |
; calculate x/y offset: (y*screen.w+x)*4 |
macro get.xy x, y |
{ . r0=y, r0*screen.w, r0+x, r0*4 } |
; address &vga[(y*screen.w+x)*4] |
function vga.xy, x, y |
get.xy x, y |
. r0+vga.p |
endf |
; draw pixel |
function draw.pixel, x, y, c |
alias p=r0, z=r1 |
try clip.pixel x, y |
vga.xy x, y |
. z=c, (u32) *p=z |
endf 1 |
; draw horizontal line |
function draw.line.h, x, y, n, c |
alias p=r0, z=r1, w=r2 |
. p=&x, z=&y, w=&n |
try clip.line 0, p, z, w |
vga.xy x, y |
. z=c |
loop n, (u32) *p++=z, endl |
endf 1 |
; draw vertical line |
function draw.line.v, x, y, n, c |
locals swb |
alias p=r0, z=r1, h=r2 |
. p=&x, z=&y, h=&n |
try clip.line 1, p, z, h |
vga.xy x, y |
. z=c, swb=screen.pitch |
loop n, (u32) *p=z, p+swb, endl |
endf 1 |
; draw solid rectangle |
function draw.box, x, y, w, h, c |
locals i |
try visible x, y, w, h |
. i=y, i-- |
loop h, i++ |
draw.line.h x, i, w, c |
endl |
endf 1 |
; draw rectangle outline |
function draw.outline, x, y, w, h, c |
try visible x, y, w, h |
draw.line.h x, y, w, c ; top |
. r0=y, r0+h, r0-- ; bottom |
draw.line.h x, r0, w, c |
. r0=y, r0++, r1=h, r1-2 ; left |
draw.line.v x, r0, r1, c |
. r0=x, r0+w, r0-- |
. r2=y, r2++, r1=h, r1-2 ; right |
draw.line.v r0, r2, r1, c |
endf 1 |
macro draw.box.s b, c |
{ draw.box b#.x, b#.y, b#.w, b#.h, c } |
macro draw.box.o b, c |
{ draw.outline b#.x, b#.y, b#.w, b#.h, c } |
macro draw.box a, b, c, d, e { |
IF ~e eq |
draw.box a, b, c, d, e |
ELSE IF ~d eq |
'Unsupported' |
ELSE IF ~c eq |
draw.box.s a, b |
draw.box.o a, c |
ELSE IF ~b eq |
draw.box.s a, b |
END IF |
} |
; draw scanline |
function draw.scanline, pixels, x, y, w |
locals i |
alias p=r0, s=r1 |
. r0=&i, r1=&x, r2=&y, r3=&w |
try clip.scanline r0, r1, r2, r3 |
vga.xy x, y |
. s=pixels, s+i |
loop w, (u32) *p++=*s++, endl |
endf 1 |
; draw scanline with transparent key |
function draw.scanline.t, pixels, x, y, w, key |
locals i |
alias p=r0, s=r1, c=r2 |
. r0=&i, r1=&x, r2=&y, r3=&w |
try clip.scanline r0, r1, r2, r3 |
vga.xy x, y |
. s=pixels, s+i |
loop w, (u32) c=*s++ |
if c<>key, (u32) *p=c, end, p+4 |
endl |
endf 1 |
; draw scanline with inverted x |
function draw.scanline.ix, pixels, x, y, w |
locals i |
alias p=r0, s=r1 |
. r0=x, r0+w |
vga.xy r0, y |
. p-4, s=pixels |
loop w, (u32) *p--=*s++, endl |
endf 1 |
; draw variant scanline. pixels are |
; grayscale, alpha intensity of co=color. |
; for brushes and special effects |
function draw.scanline.v, pixels, x, y, w, co |
locals a, i |
alias p=r0, s=r1, c=r2, c2=r3 |
. r0=&i, r1=&x, r2=&y, r3=&w |
try clip.scanline r0, r1, r2, r3 |
vga.xy x, y |
. s=pixels, s+i |
loop w, (u32) c=*s++ |
. a=c, a&0FFh |
if a=0, go .next, end |
if a=0FFh, c=co, go .draw, end |
. (u32) c2=*p |
push p s |
get c=mix co, c2, a |
pop s p |
.draw: . (u32) *p=c |
.next: . p+4 |
endl |
endf 1 |
; draw bitmap |
function draw.bitmap, pixels, x, y, w, h |
locals i, p |
try visible x, y, w, h |
. i=y, p=pixels |
loop h |
draw.scanline p, x, i, w |
. r0=w, r0*4, p+r0, i++ |
endl |
endf 1 |
; draw bitmap with transparency by |
; upper left pixel color (X=0, Y=0) |
function draw.bitmap.t, pixels, x, y, w, h |
locals i, p, key |
try visible x, y, w, h |
. i=y, r0=pixels, p=r0 |
. (u32) r0=*r0, key=r0 |
loop h |
draw.scanline.t p, x, i, w, key |
. r0=w, r0*4, p+r0, i++ |
endl |
endf 1 |
; draw bitmap with inverted x |
function draw.bitmap.ix, pixels, x, y, w, h |
locals i, p |
try visible x, y, w, h |
. p=pixels |
loop h |
draw.scanline.ix p, x, y, w |
. r0=w, r0*4, p+r0, y++ |
endl |
endf 1 |
; draw bitmap with inverted y |
function draw.bitmap.iy, pixels, x, y, w, h |
locals i, p |
try visible x, y, w, h |
. r0=h, r0--, y+r0, p=pixels |
loop h |
draw.scanline p, x, y, w |
. r0=w, r0*4, p+r0, y-- |
endl |
endf 1 |
; draw bitmap with both inverted |
function draw.bitmap.ixy, pixels, x, y, w, h |
locals i, p, n |
try visible x, y, w, h |
. p=pixels |
loop h |
draw.scanline.ix p, x, y, w |
. r0=w, r0*4, p+r0, y-- |
endl |
endf 1 |
; draw variant bitmap |
function draw.bitmap.v, pixels, x, y, w, h, c |
locals i, p |
try visible x, y, w, h |
. i=y, r0=pixels, p=r0 |
loop h |
draw.scanline.v p, x, i, w, c |
. r0=w, r0*4, p+r0, i++ |
endl |
endf 1 |
; draw gradual vertical fade from |
; color a to b. o/rient: |
; 'h'=horizontal, 'v'=vertical |
function draw.fade, bo, c1, c2 |
locals x, y, w, h, i, n, c,\ |
r, g, b, red, green, blue,\ |
nr, ng, nb, first, last |
. r0=bo,\ |
x=[?box.x+r0], y=[?box.y+r0],\ |
w=[?box.w+r0], h=[?box.h+r0] |
. r0=y, first=r0, r1=h |
. n=r1, r0+r1, last=r0 |
. r0=&r, r1=&g, r2=&b |
get.rgb c1, r0, r1, r2 |
. r0=&red, r1=&green, r2=&blue |
get.rgb c2, r0, r1, r2 |
. r<<8, g<<8, b<<8, r1=n |
if r1=0, r1++, end |
. r0=red, r0<<8, r0-r, r0/r1, nr=r0 |
. r0=green, r0<<8, r0-g, r0/r1, ng=r0 |
. r0=blue, r0<<8, r0-b, r0/r1, nb=r0 |
. i=first |
forever |
. r0=r, r0>>8, r1=g, r1>>8, r2=b, r2>>8 |
get c=rgb r0, r1, r2 |
draw.line.h x, i, w, c |
. r0=nr, r+r0, r1=ng, g+r1, r2=nb, b+r2 |
. i++, r0=last |
if i>r0, go .out, end |
endfv |
.out: |
endf |
; draw with vertical center fade: |
; a to b then b to a |
function draw.shade, bo, a, b |
memory.copy g.box, bo, 16 |
. g.box.h>>>1 |
draw.fade g.box, a, b |
. r0=g.box.h, g.box.y+r0 |
draw.fade g.box, b, a |
endf |
;;;;;;;;;;;;;;;;; PALETTE PIXELS ;;;;;;;;;;;;;;;;; |
; 8BPP versions with pa/lette. no clipping |
function draw.scanline.8, pixels, x, y, w |
alias p=r0, s=r1, c=r2, q=r3 |
vga.xy x, y |
. s=pixels |
loop w, q=*s++, q*4, q+palette.p |
. (u32) c=*q, (u32) *p++=c |
endl |
endf 1 |
function draw.bitmap.8, pixels, x, y, w, h |
locals i, p |
try visible x, y, w, h |
. i=y, i--, p=pixels |
loop h, i++ |
draw.scanline.8 p, x, i, w |
. r0=w, p+r0 |
endl |
endf 1 |
;;;;;;;;;;;;;;;;;;;;; SPECIAL ;;;;;;;;;;;;;;;;;;;; |
; special variant 8BPP with alpha bias for |
; fonts and sketching effects (example: |
; chalkboard) |
A.LIGHTEST=128 |
A.LIGHTER=96 |
A.LIGHT=64 |
A.DARK=-32 |
A.DARKER=-64 |
A.DARKEST=-96 |
align |
integer alpha.bias=0 ; A.DARKEST |
function draw.scanline.v.8, pixels, x, y, w, co |
locals a, i |
alias p=r0, s=r1, c=r2, c2=r3, q=r3 |
vga.xy x, y |
. s=pixels |
loop w, q=*s++, q*4, q+palette.p |
. (u32) c=*q, a=c, a&0FFh |
if a=0, go .next, end |
. (u32) c2=*p |
push p s |
. r0=a |
if alpha.bias, r0+alpha.bias |
if r0<0, r0=0 |
else.if r0>255, r0=255, end |
end |
get c=mix co, c2, r0 |
pop s p |
.draw: . (u32) *p=c |
.next: . p+4 |
endl |
endf 1 |
function draw.bitmap.v.8, pixels, x, y, w, h, c |
locals i, p |
try visible x, y, w, h |
. i=y, i--, p=pixels |
loop h, i++ |
draw.scanline.v.8 p, x, i, w, c |
. r0=w, p+r0 |
endl |
endf 1 |
/programs/games/codemaster/INCLUDE/DRAWK.INC |
---|
0,0 → 1,344 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ?????????????????? DRAW.INC ???????????????????? |
; fast portable graphics |
include 'color.inc' |
include 'box.inc' |
;;;;;;;;;;;;;;;;;;;;; SCREEN ;;;;;;;;;;;;;;;;;;;;; |
align |
vga equ (gs:r0) |
; void vga.p |
integer \ |
screen.w, screen.h, screen.n,\ |
screen.size, screen.pitch,\ |
screen.bpp, screen.pw |
void palette.p |
function set.screen, w, h, bpp |
alias n=r0, pw=r1 |
. screen.w=w, screen.h=h ; size |
. n=w, n*h, screen.n=n ; # pixels |
. n=bpp, n>>>3, pw=n ; pixel width |
. screen.pw=pw, n*pw ; size |
. screen.size=n ; in bytes |
. n=w, n*4 ; width |
. screen.pitch=n ; in bytes |
. screen.bpp=bpp ; bits per pixel |
endf |
; calculate x/y offset: (y*screen.w+x)*4 |
macro xy x, y { |
. r0=y, r0*1024, r0+x, r0*4 |
. r1=WINDOW.Y, r1*4096, r0+r1 |
. r1=WINDOW.X, r1*4, r0+r1 |
} |
; erase screen with color |
function clear.screen, c |
callf draw.box, 0, 0, WINDOW.W-1, WINDOW.H-1, c |
endf |
; draw straight line: loop n, *p++=c |
function draw.line.h, x, y, w, c |
xy x, y |
. r1=c |
loop w, (u32) *vga=r1, r0+4, endl |
endf |
; draw vertical line |
function draw.line.v, x, y, n, c |
locals swb |
alias p=r0, z=r1, h=r2 |
xy x, y |
. z=c, swb=4096 |
loop n, (u32) *vga=z, p+swb, endl |
endf 1 |
; draw solid rectangle |
function draw.box, x, y, w, h, c |
try visible x, y, w, h |
loop h |
draw.line.h x, y, w, c |
. y++ |
endl |
endf |
; draw rectangle outline |
function draw.outline, x, y, w, h, c |
try visible x, y, w, h |
draw.line.h x, y, w, c |
. r0=y, r0+h, r0-- |
draw.line.h x, r0, w, c |
. r0=y, r0++, r1=h, r1-2 |
draw.line.v x, r0, r1, c |
. r0=x, r0+w, r0-- |
. r1=y, r1++, r2=h, r2-2 |
draw.line.v r0, r1, r2, c |
endf |
macro draw.box.s b, c |
{ draw.box b#.x, b#.y, b#.w, b#.h, c } |
macro draw.box.o b, c |
{ draw.outline b#.x, b#.y, b#.w, b#.h, c } |
macro draw.box a, b, c, d, e { |
IF ~e eq |
draw.box a, b, c, d, e |
ELSE IF ~d eq |
'Unsupported' |
ELSE IF ~c eq |
draw.box.s a, b |
draw.box.o a, c |
ELSE IF ~b eq |
draw.box.s a, b |
END IF |
} |
; draw scanline: multi-color line, |
; array of pixels: |
; loop w, *p++=*s++, endl |
function draw.scanline, s, x, y, w |
alias p=r0, q=r1, c=r2 |
xy x, y |
. q=s |
loop w, (u32) c=*q, (u32) *vga=c |
. p+4, q+4 |
endl |
endf |
; draw transparent scanline with color |
; "key" to exclude |
function draw.scanline.t, s, x, y, w, k |
alias p=r0, q=r1, c=r2 |
xy x, y |
. q=s |
loop w, (u32) c=*q |
if c<>k, (u32) *vga=c, end |
. p+4, q+4 |
endl |
endf |
; draw scanline with inverted x |
function draw.scanline.ix, pixels, x, y, w |
alias p=r0, s=r1, c=r2 |
. r0=x, r0+w |
xy r0, y |
. p-4, s=pixels |
loop w, (u32) c=*s++, (u32) *vga=c, p-4, endl |
endf 1 |
; draw variant scanline. pixels are |
; grayscale, alpha intensity of co=color. |
; for brushes and special effects |
function draw.scanline.v, pixels, x, y, w, co |
locals a |
alias p=r0, s=r1, c=r2, c2=r3 |
xy x, y |
. s=pixels |
loop w, (u32) c=*s++ |
. a=c, a&0FFh |
if a=0, go .next, end |
if a=0FFh, c=co, go .draw, end |
. (u32) c2=*p |
push p s |
get c=mix co, c2, a |
pop s p |
.draw: . (u32) *vga=c |
.next: . p+4 |
endl |
endf 1 |
; draw transparent scanline with key and |
; alpha (0-255) applied to entire line |
function draw.scanline.a, s, x, y, w, k, a |
alias p=r0, q=r1, c=r2, c2=r3 |
xy x, y |
. q=s |
loop w, (u32) c=*q |
if c<>k, (u32) c2=*vga |
push p q |
get c=mix c, c2, a |
pop q p |
end, (u32) *vga=c |
.next: |
. p+4, q+4 |
endl |
endf |
; draw bitmap; 2D array of pixels |
function draw.bitmap, p, x, y, w, h |
locals i |
try visible x, y, w, h |
. i=y |
loop h, i++ |
draw.scanline p, x, i, w |
. r0=w, r0*4, p+r0 |
endl |
endf |
; draw transparent bitmap with color |
; "key" by upper left pixel (X0,Y0) |
function draw.bitmap.t, p, x, y, w, h |
locals i, k |
try visible x, y, w, h |
. r0=p, (u32) r0=*r0, k=r0 |
. i=y |
loop h, i++ |
draw.scanline.t p, x, i, w, k |
. r0=w, r0*4, p+r0 |
endl |
endf |
; draw transparent bitmap with key and |
; alpha (0-255) applied to entire image |
function draw.bitmap.a, p, x, y, w, h, a |
locals i, k |
try visible x, y, w, h |
. i=y, r0=p, (u32) r0=*r0, k=r0 |
loop h, i++ |
draw.scanline.a p, x, i, w, k, a |
. r0=w, r0*4, p+r0 |
endl |
endf |
; draw bitmap with inverted x |
function draw.bitmap.ix, pixels, x, y, w, h |
locals p |
try visible x, y, w, h |
. p=pixels |
loop h |
draw.scanline.ix p, x, y, w |
. r0=w, r0*4, p+r0, y++ |
endl |
endf 1 |
; draw bitmap with inverted y |
function draw.bitmap.iy, pixels, x, y, w, h |
locals p |
try visible x, y, w, h |
. r0=h, r0--, y+r0, p=pixels |
loop h |
draw.scanline p, x, y, w |
. r0=w, r0*4, p+r0, y-- |
endl |
endf 1 |
; draw bitmap with both inverted |
function draw.bitmap.ixy, pixels, x, y, w, h |
locals p, n |
try visible x, y, w, h |
. p=pixels |
loop h |
draw.scanline.ix p, x, y, w |
. r0=w, r0*4, p+r0, y-- |
endl |
endf 1 |
; draw variant bitmap |
function draw.bitmap.v, pixels, x, y, w, h, c |
locals i, p |
try visible x, y, w, h |
. i=y, r0=pixels, p=r0 |
loop h |
draw.scanline.v p, x, i, w, c |
. r0=w, r0*4, p+r0, i++ |
endl |
endf 1 |
;;;;;;;;;;;;;;;;; PALETTE PIXELS ;;;;;;;;;;;;;;;;; |
; 8BPP versions with pa/lette. no clipping |
function draw.scanline.8, pixels, x, y, w |
alias p=r0, s=r1, c=r2, q=r3 |
xy x, y |
. s=pixels |
loop w, q=*s++, q*4, q+palette.p |
. (u32) c=*q, (u32) *vga=c, r0+4 |
endl |
endf 1 |
function draw.bitmap.8, pixels, x, y, w, h |
locals i, p |
try visible x, y, w, h |
. i=y, p=pixels |
loop h |
draw.scanline.8 p, x, i, w |
. i++, r0=w, p+r0 |
endl |
endf 1 |
;;;;;;;;;;;;;;;;;;;;; SPECIAL ;;;;;;;;;;;;;;;;;;;; |
; special variant 8BPP with alpha bias for |
; fonts and sketching effects (example: |
; chalkboard) |
A.LIGHTEST=128 |
A.LIGHTER=96 |
A.LIGHT=64 |
A.DARK=-32 |
A.DARKER=-64 |
A.DARKEST=-96 |
align |
integer alpha.bias=0 ; A.DARKEST |
function draw.scanline.v.8, pixels, x, y, w, co |
locals a |
alias p=r0, s=r1, c=r2, c2=r3, q=r3 |
xy x, y |
. s=pixels |
loop w, q=*s++, q*4, q+palette.p |
. (u32) c=*q, a=c, a&0FFh |
if a=0, go .next, end |
. (u32) c2=*vga |
push p s |
. r0=a |
if alpha.bias, r0+alpha.bias |
if r0<0, r0=0 |
else.if r0>255, r0=255, end |
end |
get c=mix co, c2, r0 |
pop s p |
.draw: . (u32) *vga=c |
.next: . p+4 |
endl |
endf 1 |
function draw.bitmap.v.8, pixels, x, y, w, h, c |
locals i, p |
try visible x, y, w, h |
. i=y, p=pixels |
loop h |
draw.scanline.v.8 p, x, i, w, c |
. i++, r0=w, p+r0 |
endl |
endf 1 |
/programs/games/codemaster/INCLUDE/FONT.INC |
---|
0,0 → 1,104 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ?????????????????? FONT.INC ???????????????????? |
; 100% portable font |
;;;;;;;;;;;;;;;;;;;; SYMBOLS ;;;;;;;;;;;;;;;;;;;;; |
; my default character arrangement: 95 symbols. |
; includes all standard visible characters |
; 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I |
; J K L M N O P Q R S T U V W X Y Z a b |
; c d e f g h i j k l m n o p q r s t u |
; v w x y z _ . ? ; : ' " , ~ ! @ # $ |
; % ^ & * ( ) [ ] { } = + - < > / \ | ` |
; symbol lookup table to convert 7BIT ASCII |
; character to index. 63=ignore (spaces, etc) |
align 4 |
FONT.SYMBOLS: db \ |
63,63,63,63,63,63,63,63, 63,63,63,63,63,63,63,63,\ |
63,63,63,63,63,63,63,63, 63,63,63,63,63,63,63,63,\ |
63,72,69,74,75,76,78,68, 80,81,79,87,70,88,64,91,\ |
00,01,02,03,04,05,06,07, 08,09,67,66,89,86,90,65,\ |
73,10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24,\ |
25,26,27,28,29,30,31,32, 33,34,35,82,92,83,77,62,\ |
94,36,37,38,39,40,41,42, 43,44,45,46,47,48,49,50,\ |
51,52,53,54,55,56,57,58, 59,60,61,84,93,85,71,63 |
NO.C=63 |
macro FONT [p] { common IMAGE p } |
align |
void font.image.p |
integer font.image.w, font.w, font.h |
integer font.color=WHITE |
macro set.font i { |
. font.image.p=i#.p, r0=i#.w |
. font.image.w=r0, r1=95, r0/r1 |
. font.w=r0, font.h=i#.h |
} |
;;;;;;;;;;;;;;;;; DRAW CHARACTER ;;;;;;;;;;;;;;;;; |
function draw.c, c, x, y |
locals i, p, iw |
try visible x, y, font.w, font.h |
. r0=FONT.SYMBOLS, r0+c, r0=*r0 |
if r0=NO.C, return, end |
. r0*font.w, r0*4, r0+font.image.p |
. p=r0, iw=font.image.w, iw*4, i=font.h |
loop i, r0=i |
if r0>=font.h, break, end |
draw.scanline p, x, y, font.w |
. r1=iw, p+r1, y++ |
endl |
endf |
;;;;;;;;;;;;;;;;;;; DRAW TEXT ;;;;;;;;;;;;;;;;;;;; |
align |
integer clip.tx=-1, clip.ty=-1 |
function draw.text, t, x, y |
locals i, n, p |
. r0=t, p=r0, i=0 |
while true ; draw all characters |
. r1=i, r1*font.w ; x=i*font.w+x |
. r1+x, r0=p, r0=*r0 ; get c |
if r0=0Dh ; return? |
. i=0, r1=font.h ; reset x |
. y+r1, p++ ; y+font.h |
go .next |
end |
. r2=y, r2-font.h ; clipping |
if r2>screen.h |
return |
end |
. r2=clip.tx |
if r2<>-1, r2-font.w |
if r1>=r2, return, end |
end |
. r2=clip.ty |
if r2<>-1, r2-font.h |
if r1>=r2, return, end |
end |
draw.c r0, r1, y ; draw |
. i++ |
.next: |
. p++, r0=p, r0=*r0 |
endw |
endf |
; get width of text=a1 with insets |
function get.text.w, t |
text.n t |
. r1=r0, r1+2, r0=font.w, r0*r1 |
endf |
/programs/games/codemaster/INCLUDE/IMAGE.INC |
---|
0,0 → 1,397 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ;;;;;;;;;;;;;;;;;;; IMAGE ;;;;;;;;;;;;;;;;;;;;;; |
; image class/object/structure |
macro IMAGE a { |
a: |
void a#.p |
integer a#.x, a#.y, a#.w, a#.h |
integer a#.bpp=32, a#.key, a#.alpha |
} |
virtual at 0 |
?image.p dd 0 |
?image.x dd 0 |
?image.y dd 0 |
?image.w dd 0 |
?image.h dd 0 |
?image.bpp dd 32 |
?image.key dd 0 |
?image.alpha dd 0 |
END virtual |
?image.box fix ?image.x |
; create image file/s with header: |
; 8 bytes: |
; byte s='I' ; signature |
; byte v=0 ; version: AABBCC.VV |
; int16 w, h ; size: w:h |
; byte bpp ; bpp: 32/24/16/15/8 |
; byte n ; # colors or 0=256+ |
; byte pixels[w*h*(bpp/8)] ; or *2 if 15 |
macro IMAGE [p] { |
forward |
local w, h |
w=0 |
h=0 |
define ?s 0 |
match a==b, p \{ |
\local ..q |
..q: inject.image b, 32 |
load w word from ..q+2 |
load h word from ..q+4 |
a: |
void a\#.p=..q+8 |
integer a\#.x, a\#.y, a\#.w=w, a\#.h=h |
integer a\#.bpp, a\#.key, a\#.alpha |
define ?s 1 |
\} |
IF ?s eq 0 |
IMAGE p |
END IF |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; load 24PP .BMP, store as .IMAGE 15/16/24/32. |
; for OSs, ROMs. warning: causes slow compile |
; with 1+ MB worth of images. to compile fast |
; without images, comment "; IMAGE name='abc'" |
macro inject.image name, bpp { |
local i, p, a, r, g, b,\ |
x, y, w, h, wb |
virtual at 0 |
p:: file CD#'/media/'#name#'.BMP' |
END virtual |
IF ~bpp in <15,16,24,32> |
'Invalid BPP' name |
END IF |
load a word from p:0 |
IF a<>'BM' |
'Invalid signature' name |
END IF |
load a byte from p:1Ch |
IF a<>24 |
'Must be 24BPP' name |
END IF |
load w dword from p:12h |
load h dword from p:16h |
db 'I', 0 |
dw w, h |
db bpp, 0 |
a=((3-((w*3)+3)) and 3) |
wb=(w*3)+a |
y=h |
WHILE y>0 |
o=36h+((y-1)*wb) |
x=0 |
WHILE x<w |
i=o+(x*3) |
load b byte from p:i |
load g byte from p:i+1 |
load r byte from p:i+2 |
IF bpp=32 |
dd (r shl 16) or (g shl 8) or b |
ELSE IF bpp=24 |
db r, g, b ; or b, g, r |
ELSE IF bpp=16 |
r=((r and 11111b)/8) shl 11 |
g=((g and 111111b)/4) shl 5 |
b=((b and 11111b)/8) |
dw r or g or b |
ELSE IF bpp=15 |
r=((r and 11111b)/8) shl 10 |
g=((g and 11111b)/8) shl 5 |
b=((b and 11111b)/8) |
dw r or g or b |
END IF |
x=x+1 |
END WHILE |
y=y-1 |
END WHILE |
} |
; insert 8BPP .BMP as .IMAGE with palette. |
; note: must use special .8 drawing |
macro inject.image.8 name { |
local i, p, a, c,\ |
x, y, w, h, wb |
virtual at 0 |
p:: file CD#'/media/'#name#'.BMP' |
END virtual |
load a word from p:0 |
IF a<>'BM' |
'Invalid signature' name |
END IF |
load a byte from p:1Ch |
IF a<>8 |
'Must be 8BPP' name |
END IF |
load w dword from p:12h |
load h dword from p:16h |
db 'I', 0 |
dw w, h |
db 8, 0 |
i=0 |
WHILE i<256 |
o=36h+(i*4) |
load b byte from p:o |
load g byte from p:o+1 |
load r byte from p:o+2 |
db b, g, r, 0 |
i=i+1 |
END WHILE |
a=((3-(w+3)) and 3) |
wb=w+a |
y=h |
WHILE y>0 |
o=436h+((y-1)*wb) |
x=0 |
WHILE x<w |
load c byte from p:o+x |
db c |
x=x+1 |
END WHILE |
y=y-1 |
END WHILE |
} |
macro IMAGE8 [p] { |
forward |
local w, h |
w=0 |
h=0 |
define ?s 0 |
match a==b, p \{ |
\local ..q |
..q: inject.image.8 b |
load w word from ..q+2 |
load h word from ..q+4 |
a: |
void a\#.p=..q+408h |
integer a\#.x, a\#.y, a\#.w=w, a\#.h=h |
integer a\#.bpp, a\#.key, a\#.alpha |
; ... |
void a\#.palette=..q+8 |
define ?s 1 |
\} |
IF ?s eq 0 |
'Error: 8BPP must specify file' |
END IF |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; unfinished, unorganized... |
; 2-DO: convert to functions. create one |
; good draw.scanline.x with bpp and type |
; BIT flags: |
; draw.scanline.x p, x, y, w, 32,\ |
; G.KEY or G.ALPHA or G.GRAY or G.INVERT.X |
macro move.image i, x, y { . i#.x=x, i#.y=y } |
macro draw.image i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.t i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.t i#.p, i#.x, i#.y, i#.w, i#.h |
} |
; draw with inverted x/y |
macro draw.image.ix i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.ix i#.p,\ |
i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.iy i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.iy i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.ixy i, x, y, ix, iy { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.ixy i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.v i, x, y, c { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.v i#.p, i#.x, i#.y, i#.w, i#.h, c |
} |
; draw rotated. warning: no clipping |
function draw.scanline.rl, pixels, x, y, w |
alias p=r0, s=r1, n=r2 |
vga.xy x, y |
. s=w, s--, s*4, s+pixels, n=screen.pitch |
loop w, (u32) *p=*s--, p+n, endl |
endf 1 |
function draw.scanline.rr, pixels, x, y, w |
alias p=r0, s=r1, n=r2 |
vga.xy x, y |
. s=pixels, n=screen.pitch |
loop w, (u32) *p=*s++, p+n, endl |
endf 1 |
function draw.bitmap.rl, pixels, x, y, w, h |
locals i, p |
try visible x, y, w, h |
. p=pixels |
loop h |
draw.scanline.rl p, x, y, w |
. r0=w, r0*4, p+r0, x++ |
endl |
endf 1 |
function draw.bitmap.rr, pixels, x, y, w, h |
locals i, p |
try visible x, y, w, h |
. r0=w, r0--, x+r0, p=pixels |
loop h |
draw.scanline.rr p, x, y, w |
. r0=w, r0*4, p+r0, x-- |
endl |
endf 1 |
macro draw.image.rl i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.rl i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.rr i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.rr i#.p, i#.x, i#.y, i#.w, i#.h |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; 8BPP with palette... |
macro draw.image.8 i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
. palette.p=i#.palette |
draw.bitmap.8 i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.v.8 i, x, y, c { |
IF ~x eq |
move.image i, x, y |
END IF |
. palette.p=i#.palette |
draw.bitmap.v.8 i#.p, i#.x, i#.y, i#.w, i#.h, c |
} |
function draw.image.v8, im, x, y, co |
locals p, w, h |
. r0=im |
. (u32) r1=*(r0+?image.p), p=r1 |
. (u32) r1=*(r0+?image.w), w=r1 |
. (u32) r1=*(r0+?image.h), h=r1 |
draw.bitmap.v.8 p, x, y, w, h, co |
endf |
function draw.bitmap.viy.8, pixels,\ |
x, y, w, h, c |
locals i, p |
try visible x, y, w, h |
. r0=h, y+r0, p=pixels |
loop h |
draw.scanline.v.8 p, x, y, w, c |
. r0=w, p+r0, y-- |
endl |
endf 1 |
function draw.image.viy.8, im, x, y, co |
locals p, w, h |
. r0=im |
. (u32) r1=*(r0+?image.p), p=r1 |
. (u32) r1=*(r0+?image.w), w=r1 |
. (u32) r1=*(r0+?image.h), h=r1 |
draw.bitmap.viy.8 p, x, y, w, h, co |
endf |
;;;;;;;;;;;;;;;;;;; LOAD .BMP ;;;;;;;;;;;;;;;;;;;; |
; load 8BPP .BMP as 32BIT pixel array. |
; if success, return allocated pixels address |
; in r0 and w/h in r1/r2. return 0 if error |
function load.bmp, file |
locals image, palette,\ |
p, s, x, y, w, h, a |
catch .error |
; load file, get size then allocate |
; 32BPP image... |
try file=load.file file |
. r1=[r0+18], r2=[r0+22] |
. w=r1, h=r2, r1*r2, r1*4 |
try image=allocate r1 |
; create and load palette... |
try palette=allocate 1024 |
. r0=file, r0+54 |
memory.copy palette, r0, 1024 |
align.n w, 4 ; get alignment value |
. a=r1 ; 0-3 bytes |
; advance to p/ixels data, point |
; s/ource at first pixel in last |
; line then read image upside down |
. p=image, r0=file, r0+54, r0+1024 |
. r1=w, r1+a, r2=h, r2--, r1*r2 |
. r0+r1, s=r0, y=h |
loop y, x=w |
loop x, r2=s, r1=*r2, r1*4 |
. r1+palette, r0=p, (u32) *r0=*r1 |
. p+4, s++ |
endl |
. r0=w, r0*2, r0+a, s-r0 |
endl |
destroy file, palette |
. r0=image, r1=w, r2=h |
return |
.error: |
destroy image, file, palette |
endf 0 |
/programs/games/codemaster/INCLUDE/IMAGEK.INC |
---|
0,0 → 1,348 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ;;;;;;;;;;;;;;;;;;; IMAGE ;;;;;;;;;;;;;;;;;;;;;; |
; image class/object/structure |
macro IMAGE a { |
a: |
void a#.p |
integer a#.x, a#.y, a#.w, a#.h |
integer a#.bpp=32, a#.key, a#.alpha |
} |
virtual at 0 |
?image.p dd 0 |
?image.x dd 0 |
?image.y dd 0 |
?image.w dd 0 |
?image.h dd 0 |
?image.bpp dd 32 |
?image.key dd 0 |
?image.alpha dd 0 |
END virtual |
?image.box fix ?image.x |
; create image file/s with header: |
; 8 bytes: |
; byte s='I' ; signature |
; byte v=0 ; version: AABBCC.VV |
; int16 w, h ; size: w:h |
; byte bpp ; bpp: 32/24/16/15/8 |
; byte n ; # colors or 0=256+ |
; byte pixels[w*h*(bpp/8)] ; or *2 if 15 |
macro IMAGE [p] { |
forward |
local w, h |
w=0 |
h=0 |
define ?s 0 |
match a==b, p \{ |
\local ..q |
..q: inject.image b, 32 |
load w word from ..q+2 |
load h word from ..q+4 |
a: |
void a\#.p=..q+8 |
integer a\#.x, a\#.y, a\#.w=w, a\#.h=h |
integer a\#.bpp, a\#.key, a\#.alpha |
define ?s 1 |
\} |
IF ?s eq 0 |
IMAGE p |
END IF |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; load 24PP .BMP, store as .IMAGE 15/16/24/32. |
; for OSs, ROMs. warning: causes slow compile |
; with 1+ MB worth of images. to compile fast |
; without images, comment "; IMAGE name='abc'" |
macro inject.image name, bpp { |
local i, p, a, r, g, b,\ |
x, y, w, h, wb |
virtual at 0 |
p:: file CD#'/media/'#name#'.BMP' |
END virtual |
IF ~bpp in <15,16,24,32> |
'Invalid BPP' name |
END IF |
load a word from p:0 |
IF a<>'BM' |
'Invalid signature' name |
END IF |
load a byte from p:1Ch |
IF a<>24 |
'Must be 24BPP' name |
END IF |
load w dword from p:12h |
load h dword from p:16h |
db 'I', 0 |
dw w, h |
db bpp, 0 |
a=((3-((w*3)+3)) and 3) |
wb=(w*3)+a |
y=h |
WHILE y>0 |
o=36h+((y-1)*wb) |
x=0 |
WHILE x<w |
i=o+(x*3) |
load b byte from p:i |
load g byte from p:i+1 |
load r byte from p:i+2 |
IF bpp=32 |
dd (r shl 16) or (g shl 8) or b |
ELSE IF bpp=24 |
db r, g, b ; or b, g, r |
ELSE IF bpp=16 |
r=((r and 11111b)/8) shl 11 |
g=((g and 111111b)/4) shl 5 |
b=((b and 11111b)/8) |
dw r or g or b |
ELSE IF bpp=15 |
r=((r and 11111b)/8) shl 10 |
g=((g and 11111b)/8) shl 5 |
b=((b and 11111b)/8) |
dw r or g or b |
END IF |
x=x+1 |
END WHILE |
y=y-1 |
END WHILE |
} |
; insert 8BPP .BMP as .IMAGE with palette. |
; note: must use special .8 drawing |
macro inject.image.8 name { |
local i, p, a, c,\ |
x, y, w, h, wb |
virtual at 0 |
p:: file CD#'/media/'#name#'.BMP' |
END virtual |
load a word from p:0 |
IF a<>'BM' |
'Invalid signature' name |
END IF |
load a byte from p:1Ch |
IF a<>8 |
'Must be 8BPP' name |
END IF |
load w dword from p:12h |
load h dword from p:16h |
db 'I', 0 |
dw w, h |
db 8, 0 |
i=0 |
WHILE i<256 |
o=36h+(i*4) |
load b byte from p:o |
load g byte from p:o+1 |
load r byte from p:o+2 |
db b, g, r, 0 |
i=i+1 |
END WHILE |
a=((3-(w+3)) and 3) |
wb=w+a |
y=h |
WHILE y>0 |
o=436h+((y-1)*wb) |
x=0 |
WHILE x<w |
load c byte from p:o+x |
db c |
x=x+1 |
END WHILE |
y=y-1 |
END WHILE |
} |
macro IMAGE8 [p] { |
forward |
local w, h |
w=0 |
h=0 |
define ?s 0 |
match a==b, p \{ |
\local ..q |
..q: inject.image.8 b |
load w word from ..q+2 |
load h word from ..q+4 |
a: |
void a\#.p=..q+408h |
integer a\#.x, a\#.y, a\#.w=w, a\#.h=h |
integer a\#.bpp, a\#.key, a\#.alpha |
; ... |
void a\#.palette=..q+8 |
define ?s 1 |
\} |
IF ?s eq 0 |
'Error: 8BPP must specify file' |
END IF |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; unfinished, unorganized... |
; 2-DO: convert to functions. create one |
; good draw.scanline.x with bpp and type |
; BIT flags: |
; draw.scanline.x p, x, y, w, 32,\ |
; G.KEY or G.ALPHA or G.GRAY or G.INVERT.X |
macro move.image i, x, y { |
IF ~x eq |
. i#.x=x, i#.y=y |
END IF |
} |
macro draw.image i, x, y { |
move.image i, x, y |
draw.bitmap i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.t i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.t i#.p, i#.x, i#.y, i#.w, i#.h |
} |
; draw with inverted x/y |
macro draw.image.ix i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.ix i#.p,\ |
i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.iy i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.iy i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.ixy i, x, y, ix, iy { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.ixy i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.v i, x, y, c { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.v i#.p, i#.x, i#.y, i#.w, i#.h, c |
} |
; draw rotated. warning: no clipping |
function draw.scanline.rl, pixels, x, y, w |
alias p=r0, s=r1, n=r2, c=r3 |
xy x, y |
. s=w, s--, s*4, s+pixels, n=4096 ; screen.pitch |
loop w, (u32) c=*s--, (u32) *vga=c, p+n, endl |
endf 1 |
function draw.scanline.rr, pixels, x, y, w |
alias p=r0, s=r1, n=r2, c=r3 |
xy x, y |
. s=pixels, n=4096 ; screen.pitch |
loop w, (u32) c=*s++, (u32) *vga=c, p+n, endl |
endf 1 |
function draw.bitmap.rl, pixels, x, y, w, h |
locals p |
try visible x, y, w, h |
. p=pixels |
loop h |
draw.scanline.rl p, x, y, w |
. r0=w, r0*4, p+r0, x++ |
endl |
endf 1 |
function draw.bitmap.rr, pixels, x, y, w, h |
locals p |
try visible x, y, w, h |
. r0=w, r0--, x+r0, p=pixels |
loop h |
draw.scanline.rr p, x, y, w |
. r0=w, r0*4, p+r0, x-- |
endl |
endf 1 |
macro draw.image.rl i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.rl i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.rr i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
draw.bitmap.rr i#.p, i#.x, i#.y, i#.w, i#.h |
} |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; 8BPP with palette... |
macro draw.image.8 i, x, y { |
IF ~x eq |
move.image i, x, y |
END IF |
. palette.p=i#.palette |
draw.bitmap.8 i#.p, i#.x, i#.y, i#.w, i#.h |
} |
macro draw.image.v.8 i, x, y, c { |
IF ~x eq |
move.image i, x, y |
END IF |
. palette.p=i#.palette |
draw.bitmap.v.8 i#.p, i#.x, i#.y, i#.w, i#.h, c |
} |
function draw.image.v8, im, x, y, co |
locals p, w, h |
. r0=im |
. (u32) r1=*(r0+?image.p), p=r1 |
. (u32) r1=*(r0+?image.w), w=r1 |
. (u32) r1=*(r0+?image.h), h=r1 |
draw.bitmap.v.8 p, x, y, w, h, co |
endf |
function draw.bitmap.viy.8, pixels,\ |
x, y, w, h, c |
locals i, p |
try visible x, y, w, h |
. r0=h, y+r0, p=pixels |
loop h |
draw.scanline.v.8 p, x, y, w, c |
. r0=w, p+r0, y-- |
endl |
endf 1 |
function draw.image.viy.8, im, x, y, co |
locals p, w, h |
. r0=im |
. (u32) r1=*(r0+?image.p), p=r1 |
. (u32) r1=*(r0+?image.w), w=r1 |
. (u32) r1=*(r0+?image.h), h=r1 |
draw.bitmap.viy.8 p, x, y, w, h, co |
endf |
/programs/games/codemaster/INCLUDE/LANGUAGE.INC |
---|
0,0 → 1,2110 |
; $$$$$$$$$$$$$$ ABA-KIS EVOLUTION $$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ???????????????? LANGUAGE.INC ?????????????????? |
;;;;;;;;;;;;;;;;;;; REGISTERS ;;;;;;;;;;;;;;;;;;;; |
r0 fix eax |
r1 fix ecx |
r2 fix edx |
r3 fix ebx |
r4 fix esp |
r5 fix ebp |
r6 fix esi |
r7 fix edi |
is.i? fix eqtype 0 |
is.m? fix eqtype [0] |
is.r? fix in \ |
<eax,ecx,edx,ebx,esp,ebp,esi,edi,\ |
ax,cx,dx,bx,al,ah,cl,ch,dl,dh,bl,bh> |
is.r32? fix in \ |
<eax,ecx,edx,ebx,esp,ebp,esi,edi> |
is.r16? fix in <ax,cx,dx,bx> |
is.r16x? fix in <ax,cx,dx,bx,sp,bp,si,di> |
is.r8l? fix in <al,cl,dl,bl> |
is.r8h? fix in <ah,ch,dh,bh> |
is.r8? fix in <al,ah,cl,ch,dl,dh,bl,bh> |
;;;;;;;;;;;;;;;;; SYNTAX, VERIFY ;;;;;;;;;;;;;;;;; |
?not fix ~ |
?empty fix eq |
macro syntax v { |
IF v eq |
define ?s 1 |
ELSE |
define ?s v |
END IF |
} |
macro verify e { |
IF ?s eq 0 |
display `e |
'Error: ' e |
END IF |
} |
if.syntax fix IF ?s eq |
if.not.syntax fix IF ?s eq 0 |
macro verify.r [r] { |
IF ~r is.r? |
'Register expected:' r |
END IF |
} |
macro verify.r32 [r] { |
IF ~r is.r32? |
'Register expected:' r |
END IF |
} |
macro verify.i i { |
IF ~i is.i? |
'Number expected:' i |
END IF |
} |
macro verify.n n, min, max { |
IF n<min | n>max |
'Number exceeds range:' min-max |
END IF |
} |
macro verify.u3 n { verify.n n, 0, 7 } |
macro verify.u4 n { verify.n n, 0, 15 } |
macro verify.u5 n { verify.n n, 0, 31 } |
macro verify.u6 n { verify.n n, 0, 63 } |
macro verify.u7 n { verify.n n, 0, 127 } |
macro verify.8 n { verify.n n, -255, 255 } |
macro verify.u8 n { verify.n n, 0, 255 } |
macro verify.i8 n { verify.n n, -128, 127 } |
macro verify.12 n { verify.n n, -4095, 4095 } |
macro verify.u12 n { verify.n n, 0, 4095 } |
macro verify.i12 n { verify.n n, -2048, 2047 } |
macro verify.16 n { verify.n n, -65535, 65535 } |
macro verify.u16 n { verify.n n, 0, 65535 } |
macro verify.i16 n { verify.n n, -32768, 32767 } |
; verify size of block/text/array |
macro verify.size n { |
IF n eq |
'Size must be specified' |
ELSE IF ~ n eqtype 0 |
'Size must be numeric' |
ELSE IF n eq 0 |
'Size cannot be zero' |
END IF |
} |
;;;;;;;;;;;;;;;;;;; ALIGNMENT ;;;;;;;;;;;;;;;;;;;; |
macro align n { |
IF n eq ; by address size |
align 4 |
ELSE |
IF n is.i? ; align n (standard) |
align n |
ELSE ; align integer i=123 |
align 4 |
n ; line after |
END IF |
END IF |
} |
macro IF.align n, by { IF n mod by=0 } |
macro IF.not.align n, by { IF n mod by<>0 } |
macro verify.a n, by { |
display.h n |
IF.not.align n, by |
'Number' n 'must be aligned by:' by |
END IF |
} |
;;;;;;;;;;;;;;;;;;;; DISPLAY ;;;;;;;;;;;;;;;;;;;;; |
; display numbers at assembly time |
macro display.b n { |
REPEAT 32 |
display '0'+((n shr (32-%)) and 1) |
END REPEAT |
} |
macro display.h n { |
local c |
REPEAT 8 |
c=(n and (0Fh shl ((8-%) shl 2))) \ |
shr ((8-%) shl 2) + '0' |
IF c>'9' |
c=c+7 |
END IF |
display c |
IF %=8 |
display 'h' |
END IF |
IF (((%*4) and 31)=0) |
display ' ' |
END IF |
END REPEAT |
} |
;;;;;;;;;;;;;;;;;; EQUATE LIST ;;;;;;;;;;;;;;;;;;; |
macro ?list.attach list, item { |
match any, list \{ list equ list, item \} |
match , list \{ list equ item \} |
} |
macro ?display.list [p] { |
common |
match q, p \{ |
?p equ q |
irps s, q \\{ |
display \\`s, ' ' |
match a b, ?p \\\{ |
restore ?p |
?p equ b |
\\\} |
\\} |
restore ?p |
\} |
} |
;;;;;;;;;;;;;;;;;;;; SETTINGS ;;;;;;;;;;;;;;;;;;;; |
; example: ?enable align |
?setting.align equ |
?setting.debug equ |
IF.align fix match =1, ?setting.align |
IF.debug fix match =1, ?setting.debug |
macro ?enable s, v { |
restore ?setting.#s |
match , v |
\{ ?setting.#s equ 1 \} |
match any, v |
\{ ?setting.#s equ v \} |
} |
macro ?disable s { |
restore ?setting.#s |
?setting.#s equ 0 |
} |
;;;;;;;;;;;;;;;;;;;; VARIABLE ;;;;;;;;;;;;;;;;;;;; |
_strict_ equ 0 ; strict type safety? |
_scope_ equ 0 ; 0=global, 1=local |
_object_ equ 0 |
; create variable: name (a), type, value, |
; size (n), sign (s) |
macro ?V a, t, v, n, s { |
IF.align \{ align \} |
IF n=8 |
!#a dq v |
ELSE IF n=4 |
!#a dd v |
ELSE IF n=2 |
!#a dw v |
ELSE IF n=1 |
!#a db v |
ELSE |
'Invalid size' |
END IF |
name$#a equ a |
type$#a=t |
size$#a=n |
sign$#a=s |
scope$#a=_scope_ |
strict$#a=_strict_ |
a equ [!#a] |
} |
; define X. syntax: type then any a/a=b |
; sequence/s separated with ,s. |
; variables=0 if there is no initial value |
macro ?D type, [p] { |
forward |
define ?s 0 |
match =0 \ |
a==b, ?s p \{ ; a=b |
type a, b |
define ?s 1 |
\} |
match =0 \ |
a=,, ?s p \{ ; a, (next) |
type a, 0 |
define ?s 1 |
\} |
match =0 \ |
a, ?s p \{ ; a (end) |
type a, 0 |
define ?s 1 |
\} |
verify variable |
} |
; real variable names... |
macro i8 a, v { ?V a, 'i', v, 1, 1 } |
macro u8 a, v { ?V a, 'i', v, 1, 0 } |
macro i16 a, v { ?V a, 'i', v, 2, 1 } |
macro u16 a, v { ?V a, 'i', v, 2, 0 } |
macro i32 a, v { ?V a, 'i', v, 4, 1 } |
macro u32 a, v { ?V a, 'i', v, 4, 0 } |
macro i64 a, v { ?V a, 'i', v, 8, 1 } |
macro u64 a, v { ?V a, 'i', v, 8, 0 } |
; aliases... |
macro void [a] { ?D u32, a } |
macro char [a] { ?D i8, a } |
macro uchar [a] { ?D u8, a } |
macro wchar [a] { ?D u16, a } |
macro short [a] { ?D i16, a } |
macro ushort [a] { ?D u16, a } |
macro int [a] { ?D i32, a } |
macro uint [a] { ?D u32, a } |
macro long [a] { ?D i64, a } |
macro ulong [a] { ?D u64, a } |
macro float [a] { ?D u32, a } |
macro double [a] { ?D u64, a } |
macro byte [a] { ?D i8, a } |
macro ubyte [a] { ?D u8, a } |
macro integer [a] { ?D i32, a } |
macro uinteger [a] { ?D u32, a } |
macro boolean [a] { ?D i32, a } |
;;;;;;;;;;;;;;;;; LITERAL TABLE ;;;;;;;;;;;;;;;; |
?literals.i=0 ; offset |
?literals equ align 4,\ |
?LITERALS:, ?literals.i=0 |
; store literal 'text'. attach line |
macro ?literal t { |
local n |
virtual at 0 |
db t, 0 |
n=$ |
END virtual |
?literals equ ?literals,\ |
db t, db 0 |
?literals.i=?literals.i+n |
} |
; store table. expand line/s |
macro @literals { |
IF ?literals.i |
match j, ?literals \{ |
irp i, j \\{ i \\} |
\} |
END IF |
} |
;;;;;;;;;;;;;;;;; TEXT VARIABLES ;;;;;;;;;;;;;;;;; |
; create HL 'text' variable/s. text t='X'. |
; note: (n) is the size |
macro text [p] { |
forward |
local l |
define ?s 0 |
match =0 \ ; text t(n)='abc' |
name(n)==t, ?s p \{ |
l=$ |
verify.size n |
name: db t, 0 |
times \ |
(n-($-l)) db 0 |
name\#.$=n |
define ?s 1 |
\} |
match =0 name(n),\ ; text t(n) |
?s p \{ |
verify.size n |
name: db n dup(0) |
name\#.$=n |
define ?s 1 |
\} |
match =0 name==t,\ ; text t='abc' |
?s p \{ |
l=$ |
name: db t, 0 |
name\#.$=($-l) |
define ?s 1 |
\} |
match =0 name, ?s p \{ |
'Size not specified:' name |
define ?s 1 |
\} |
verify name |
} |
; helper macros: text/x/a/i/p |
; text extended to 2+ lines: |
; text name=+'Hi, how ',\ |
; 'are ', 'you?' |
macro textx name, [p] { |
common |
name: db p, 0 |
} |
; create array of pointers and literal |
; 'text'. optional a/lign each to size |
; or 0=none: |
; text names[]='ann', 'kim', 'sue' |
macro texta a, name, [t] { |
common |
local n |
n=0 |
label name dword |
forward |
local l |
dd l |
n=n+1 |
forward |
l db t, 0 |
IF a |
times (a-($-l)) db 0 |
END IF |
common |
name#.$=n |
} |
; like texta with ids (0-n): |
; textai 0, names.ta, 'ann', 'kim', 'sue' |
macro textai a, name, [p] { |
common |
local n |
n=0 |
label name dword |
forward |
local l |
dd l |
forward |
define ?s 0 |
match id==t, p \{ |
l db t, 0 |
id=n |
n=n+1 |
define ?s 1 |
\} |
verify textai |
IF a |
times (a-($-l)) db 0 |
END IF |
common |
name#.$=n |
} |
; same with prefix |
macro textaip a, name, x, [p] { |
common |
local n |
n=0 |
label name dword |
forward |
local l |
dd l |
forward |
define ?s 0 |
match id==t, p \{ |
l db t, 0 |
x\#id=n |
n=n+1 |
define ?s 1 |
\} |
verify textaip |
IF a |
times (a-($-l)) db 0 |
END IF |
common |
name#.$=n |
} |
; upgrade text to support ()/textx/a/i/p |
macro text [p] { |
common |
define ?s 0 |
match =0 (n), ?s p \{ |
db n dup(0) |
define ?s 1 |
\} |
match =0 a==+b, ?s p \{ |
textx a, b |
define ?s 1 |
\} |
match =0 \ |
a[]==name* t, ?s p \{ |
match x==y, t \\{ |
textaip 0, a, name, t |
define ?s 1 |
\\} |
IF ?s eq 0 |
texta 0, a, t |
END IF |
define ?s 1 |
\} |
match =0 \ |
a[]==t, ?s p \{ |
match x==y, t \\{ |
textai 0, a, t |
define ?s 1 |
\\} |
IF ?s eq 0 |
texta 0, a, t |
END IF |
define ?s 1 |
\} |
match =0 \ |
a[](n)==t, ?s p \{ |
texta n, a, t |
define ?s 1 |
\} |
IF ?s eq 0 |
text p |
END IF |
} |
; create 'text' in code. r/egister='t/ext' |
; WARNING: all commands that accept a literal |
; 'text' parameter (.t suffix) will alter eax. |
; only intended for testing and utilities |
macro make.txt r, t { |
IF t eqtype "" |
local ..t, ..e |
jmp ..e |
..t db t, 0 |
..e: |
mov r, ..t |
ELSE |
mov r, t |
END IF |
} |
;;;;;;;;;;;;;;; VARIABLE EXAMPLES ;;;;;;;;;;;;;; |
; variables: void, int, float, x |
; int i, n=123 |
; void p |
; float f=1.0, g=0.5 |
; double d, e=7.25 |
; text t='ABC', name(64) ; byte[] |
; extended 2+ lines: |
; text name=+'Hi, how ',\ |
; 'are ', 'you?' |
; void[]+'text'... |
; text ta[]='A', '123' |
; with alignment: |
; text names[](8)='ann', 'kim', 'sue' |
; with numeric ID #s (0-n): |
; text xyz[]= \ |
; ID.A='A', ID.B='B', ID.C='C' |
; with prefix + ID #s (ERROR.NAME): |
; text errors[]= ERROR.* \ |
; NONE = 'No error',\ |
; SYNTAX = 'Syntax',\ |
; ADDRESS = 'Invalid address',\ |
; MEMORY = 'Memory allocation',\ |
; SETUP = 'Initiation' |
; access text from pointer array: |
; mov eax, [ta+3*4] |
; say [errors+ERROR.MEMORY*4] |
;;;;;;;;;;;;;; NUMERIC CONSTANTS ;;;;;;;;;;;;;;;;; |
; create incremental (0-n) list of numeric |
; constants with optional prefix. each token |
; can be assigned or it equals previous+1. |
; if first token ends with *, it becomes the |
; prefix for subsequent tokens. example: |
; numeric COLOR.*,\ |
; BLACK, WHITE, RED, GREEN, BLUE |
; COLOR.BLACK=0 ; output... |
; COLOR.WHITE=1 |
; COLOR.RED=2 |
; COLOR.GREEN=3 |
; COLOR.BLUE=4 |
macro numeric ?p, [p] { |
common |
local n |
n=0 ; n=0 |
syntax 0 |
match z$*, ?p \{ ; extract prefix |
syntax 1 |
\} |
match a==b, ?p \{ ; first item |
a=b |
n=b+1 |
syntax 1 |
\} |
match =0, ?s \{ ; else, first=0 |
?p=0 |
n=1 |
\} |
forward |
syntax 0 |
match a==b, p \{ ; assigment? |
n=b ; set n |
match z$*, ?p \\{ ; extract prefix |
z$\\#a=b |
syntax 1 |
\\} |
if.syntax 0 ; no prefix |
a=b |
END IF |
syntax 1 ; yes, specified |
\} |
match =0, ?s \{ ; else=n (previous+1) |
match z$*, ?p \\{ ; extract prefix |
z$\\#p=n |
syntax 1 |
\\} |
if.syntax 0 ; no prefix |
p=n |
END IF |
\} |
n=n+1 ; n++ |
} |
KB=1024 ; 1<<10 |
MB=1048576 ; 1<<20 |
GB=1073741824 ; 1<<30 |
numeric YES=1, NO=0, TRUE=1, FALSE=0,\ |
NULL=0, DEFAULT=0, NONE=-1, INVALID=-1,\ |
DETECT=-1, INFINITE=-1, NOTHING=-1 |
; note: -1 means "not zero and not maximum" |
; (FFFF/FF/FFh) for indices, sizes, handles |
; (index or pointer), etc, where >=0 is |
; valid/finite/something... |
; if n=INFINITE ; if -1 |
; if handle=INVALID ; if -1 |
; if n not INVALID ; if <>-1 |
; if win>NOTHING ; if >=0 |
;;;;;;;;;;;;;;;;;;;;; POWERS ;;;;;;;;;;;;;;;;;;;;; |
; create successive powers of 2 starting |
; at BIT0, from right to left. example: |
; powers IS.*, ACTIVE, VISIBLE,\ |
; DRAWABLE, MOVEABLE, SIZABLE |
macro _powers [id] { |
common local n |
n=0 |
forward id=1 shl n |
n=n+1 |
} |
macro powers ?p, [p] { |
common |
local n |
n=0 ; n=1 |
syntax 0 |
match z$*, ?p \{ ; extract prefix |
syntax 1 |
\} |
match =0, ?s \{ ; else, first item |
?p=0 |
n=1 |
\} |
forward |
syntax 0 |
match a==b, p \{ ; assigment? |
n=b ; set n |
match z$*, ?p \\{ ; extract prefix |
z$\\#a=1 shl n |
syntax 1 |
\\} |
if.syntax 0 ; no prefix |
a=1 shl n |
END IF |
syntax 1 ; yes, specified |
\} |
match =0, ?s \{ ; else=n (previous+1) |
match z$*, ?p \\{ ; extract prefix |
z$\\#p=1 shl n |
syntax 1 |
\\} |
if.syntax 0 ; no prefix |
p=1 shl n |
END IF |
\} |
n=n+1 ; next bit |
} |
; create readable bit structure from |
; left to right. example: 0000ABCDb. |
; powerz A, B, C, D ; A=8, B=4, C=2, D=1 |
macro powerz [id] { |
common local n |
n=1 |
forward n=n+1 |
common n=n-2 |
forward id=1 shl n |
n=n-1 |
} |
; get power of 2. n-1 then search from left |
; to right for 1st 0 BIT. rv=return value |
; n=0 |
; ?power.2 256, n |
; say.n n |
macro ?power.2 n, rv { |
local i, x |
i=0 |
IF (n and (n-1))=0 |
i=1 |
x=n-1 |
WHILE 1 |
IF x and (1 shl i)=0 |
?break |
END IF |
i=i+1 |
END WHILE |
END IF |
rv=i |
} |
;;;;;;;;;;;;;;;;;;;; IF BIT/S ;;;;;;;;;;;;;;;;;;;; |
; compare BITs in r or eax. alters edx |
; if.bit 20 |
; if.bits 4-7=1001b |
; if.bit 20, eax |
; if.bits 31-24=11110011b, eax |
macro if.bit n, r { |
IF ~r eq |
mov edx, r |
ELSE |
mov edx, eax |
END IF |
local ..start, ..else, ..end |
?IF equ |
?START equ ..start |
?ELSE equ ..else |
?END equ ..end |
?START: |
test edx, (1 shl n) |
jz ?ELSE |
} |
macro if.not.bit n, r { |
IF ~r eq |
mov edx, r |
ELSE |
mov edx, eax |
END IF |
local ..start, ..else, ..end |
?IF equ |
?START equ ..start |
?ELSE equ ..else |
?END equ ..end |
?START: |
test edx, (1 shl n) |
jnz ?ELSE |
} |
; alters edx |
macro if.bits n, r { |
local i, b,\ |
lo, hi, mask |
syntax 0 |
match l-h==v, n \{ ; BITs = value |
IF l<h ; low to high |
lo=l |
hi=h |
ELSE ; high to low |
lo=h |
hi=l |
END IF |
i=0 ; search value from |
REPEAT 32 ; left to right (31-0) |
IF v and \ ; for 1st BIT set... |
(1 shl (31-i))<>0 |
?break |
END IF |
i=i+1 |
END REPEAT |
b=0 ; # BITs required |
REPEAT 32-i ; for v/alue |
b=b+1 |
END REPEAT |
IF b>(hi-lo+1) ; example: 4-5=111b |
'Value exceeds size' ; 4-5 is only 2BITs, |
END IF ; not enough for 111b. |
i=0 |
mask=0 ; create mask: 111xb |
REPEAT (hi-lo+1) ; # 1 BITs |
mask=\ |
(mask or (1 shl i)) |
i=i+1 |
END REPEAT |
local ..start, ..else, ..end |
?IF equ |
?START equ ..start |
?ELSE equ ..else |
?END equ ..end |
IF ~r eq |
mov edx, r |
ELSE |
mov edx, eax |
END IF |
shr edx, lo ; extract BITs |
and edx, mask |
?START: |
cmp edx, v |
jne ?ELSE |
syntax 1 |
\} |
verify |
} |
;;;;;;;;;;;;;;;;;;;;; CLASS ;;;;;;;;;;;;;;;;;;;;;; |
; unfinished |
; macro class name { |
; name: |
; macro u8 a, v \{ u8 name\#.\#a, v \} |
; macro i8 a, v \{ i8 name\#.\#a, v \} |
; macro u16 a, v \{ u16 name\#.\#a, v \} |
; macro i16 a, v \{ i16 name\#.\#a, v \} |
; macro u32 a, v \{ u32 name\#.\#a, v \} |
; macro i32 a, v \{ i32 name\#.\#a, v \} |
; macro u64 a, v \{ u64 name\#.\#a, v \} |
; macro i64 a, v \{ i64 name\#.\#a, v \} |
; ... |
; } |
; |
; macro endc [p] { |
; common |
; restore u8, i8, u16, i16,\ |
; u32, i32, u64, i64 |
; } |
; 2-DO: single-line classes: |
; class RGB = byte a, r, g, b |
; class POINT = integer x, y |
; class LINE = POINT a, b |
; class BOX = integer x, y, w, h |
; class POINT3D = integer x, y, z |
; class POLYGON = ARRAY POINT3D points[] |
macro assume [p] { |
common |
match name==type, p \{ |
virtual at 0 |
type name |
END virtual |
\} |
} |
;;;;;;;;;;;;;;;;; LET ARITHMETIC ;;;;;;;;;;;;;;;;; |
; perform assignment/s, operation/s and |
; low-level "expressions". |
; signed is the default for numbers that can |
; be negative (ex, coordinates). some symbols |
; are for unsigned operations (>>> is shr) |
; = is a standard copy, move, assignment |
; =& gets the address of integers/void/x |
; WARNING: both ++/--/+-/-+ cannot used. |
; replace let eax+[?image.x+edx] (has 2 ++) |
; with: let ecx=[?image.x+edx], eax+ecx |
macro let [p] { |
forward |
define ?s 0 |
; a=&b, lea r, [b] |
match =0 a==&(b), ?s p \{ |
lea a, [b] |
define ?s 1 |
\} |
match =0 a==&b, ?s p \{ |
lea a, b |
define ?s 1 |
\} |
match =0 a><b, ?s p \{ |
xor a, b |
define ?s 1 |
\} |
; a=b, mov or push/pop or xor |
match =0 a==b, ?s p \{ |
IF a eqtype [] & b eqtype [] ; m=m |
push dword b |
pop dword a |
ELSE |
IF b eq 0 & \ |
a in <eax,ecx,edx,ebx,esi,edi> |
xor a, a |
ELSE |
mov a, b |
END IF |
END IF |
define ?s 1 |
\} |
; binary and/or |
match =0 a&b, ?s p \{ and a, b |
define ?s 1 \} |
match =0 a|b, ?s p \{ or a, b |
define ?s 1 \} |
; shifts. note: >>> must be matched |
; before >> or there will be a partial match |
match =0 a>>>b, ?s p \{ shr a, b |
define ?s 1 \} |
match =0 a<<b, ?s p \{ sal a, b |
define ?s 1 \} |
match =0 a>>b, ?s p \{ sar a, b |
define ?s 1 \} |
match =0 a<>>b, ?s p \{ ror a, b |
define ?s 1 \} |
; increment/decrement. must be matched |
; before a-b, a+b |
match =0 a--, ?s p \{ |
dec a |
define ?s 1 |
\} |
match =0 a++, ?s p \{ |
inc a |
define ?s 1 |
\} |
; add/subtract |
match =0 a-b, ?s p \{ |
IF b eq 1 |
dec a |
ELSE |
sub a, b |
END IF |
define ?s 1 |
\} |
match =0 a+b, ?s p \{ |
IF b eq 1 |
inc a |
ELSE |
add a, b |
END IF |
define ?s 1 |
\} |
; multiply. 2/4/8/16 will be optimized |
; and replaced with shift left 1/2/3/4 |
match =0 a*b, ?s p \{ |
IF b eq 2 |
sal a, 1 |
ELSE IF b eq 4 |
sal a, 2 |
ELSE IF b eq 8 |
sal a, 3 |
ELSE IF b eq 16 |
sal a, 4 |
ELSE |
imul a, b |
END IF |
define ?s 1 |
\} |
; divide. a: must be eax or m/2/4/8/16. |
; b: must be m, ecx or 2/4/8/16. |
; example: eax=n/123 may be written as: |
; let eax=n, ecx=123, eax/ecx |
; ... instead of 4 separate lines |
match =0 a/b, ?s p \{ |
IF b eq 2 |
sar a, 1 |
ELSE IF b eq 4 |
sar a, 2 |
ELSE IF b eq 8 |
sar a, 3 |
ELSE IF b eq 16 |
sar a, 4 |
ELSE |
IF a eq eax |
cdq |
idiv b |
ELSE |
'Unsupported' |
END IF |
END IF |
define ?s 1 |
\} |
; jmp/jz/jnz. only support the most |
; common ones for fast assembly speed... |
match =0 =jmp l, ?s p \{ |
jmp l |
define ?s 1 |
\} |
match =0 =jz l, ?s p \{ |
jz l |
define ?s 1 |
\} |
match =0 =jnz l, ?s p \{ |
jnz l |
define ?s 1 |
\} |
; unary prefixes |
match =0 -a, ?s p \{ |
neg a |
define ?s 1 |
\} |
match =0 =neg a, ?s p \{ |
neg a |
define ?s 1 |
\} |
match =0 =not a, ?s p \{ |
not a |
define ?s 1 |
\} |
match =0 =bswap a, ?s p \{ |
bswap a |
define ?s 1 |
\} |
match =0 xchg(a=,b), ?s p \{ |
xchg a, b |
define ?s 1 |
\} |
match =0 =mul a, ?s p \{ |
mul a |
define ?s 1 |
\} |
match =0 =div a, ?s p \{ |
div a |
define ?s 1 |
\} |
verify let |
} |
;;;;;;;;;;;;;;;;; GET SIZE/SIGN ;;;;;;;;;;;;;;;;;; |
; from t=type name, return s=size and |
; i=sign in numeric constants. example: |
; size=0 |
; sign=0 |
; @gets i32, size, sign ; s=32, i=1 |
macro @gets t, s, i { |
s=0 |
i=0 |
IF t eq u32 | t eq i32 | t eq dword |
s=32 |
ELSE IF t eq u16 | t eq i16 | t eq word |
s=16 |
ELSE IF t eq u8 | t eq i8 | t eq byte |
s=8 |
ELSE |
'Unknown type' |
END IF |
IF t eq i32 | t eq i16 | t eq i8 |
i=1 |
END IF |
} |
;;;;;;;;;;;;;;; POINTER ARITHMETIC ;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;; GET/SET VALUE ;;;;;;;;;;;;;;;;; |
; helper load/store... |
; t=type, r=register, v=value, |
; s=size, i=sign |
macro @gv t, r, v, s, i { |
IF s=32 |
mov r, v |
ELSE IF s=8 |
IF i=1 |
movsx r, byte v |
ELSE |
movzx r, byte v |
END IF |
ELSE IF s=16 |
IF i=1 |
movsx r, word v |
ELSE |
movzx r, word v |
END IF |
END IF |
} |
macro @get t, r, [v] { |
common |
local s, i ; get size |
@gets t, s, i ; and sign |
define ?s 0 |
match *a, v \{ ; *p |
match x++, a \\{ ; *p++ |
?a equ x |
?o equ add |
define ?s 1 |
\\} |
match =0 \ |
x--, ?s a \\{ ; *p-- |
?a equ x |
?o equ sub |
define ?s 1 |
\\} |
match =0 x, ?s a \\{ ; else, *p |
?a equ x |
?o equ ; no advance |
define ?s 1 |
\\} |
IF ~ ?a is.r? |
'Error' |
END IF |
@gv t, r, [?a], s, i ; get value |
IF ~ ?o eq ; advance? |
?o ?a, s/8 ; add/sub n |
END IF |
verify |
\} |
match =0 a, ?s v \{ ; r |
@gv t, r, a, s, i |
define ?s 1 |
\} |
verify |
restore ?a, ?o |
} |
; t=type, r=register, v=value |
macro @sv t, r, v { |
IF t eq u32 | t eq i32 | t eq dword |
mov dword v, r |
ELSE IF t eq u16 \ |
| t eq i16 | t eq word |
IF r eq eax |
mov v, ax |
ELSE IF r eq ecx |
mov v, cx |
ELSE IF r eq edx |
mov v, dx |
ELSE IF r eq ebx |
mov v, bx |
ELSE ; assume i |
mov dword v, r |
END IF |
ELSE IF t eq u8 \ |
| t eq i8 | t eq byte |
IF r eq eax |
mov v, al |
ELSE IF r eq ecx |
mov v, cl |
ELSE IF r eq edx |
mov v, dl |
ELSE IF r eq ebx |
mov v, bl |
ELSE ; assume i |
mov dword v, r |
END IF |
ELSE |
'Unknown type/size' |
END IF |
} |
macro @set t, r, [v] { |
common |
local s, i ; get size |
@gets t, s, i ; and sign |
define ?s 0 |
match *a, v \{ ; *p |
match x++, a \\{ ; *p++ |
?a equ x |
?o equ add |
define ?s 1 |
\\} |
match =0 \ |
x--, ?s a \\{ ; *p-- |
?a equ x |
?o equ sub |
define ?s 1 |
\\} |
match =0 x, ?s a \\{ ; else, *p |
?a equ x |
?o equ ; no advance |
define ?s 1 |
\\} |
IF ~ ?a is.r? |
'Error' |
END IF |
@sv t, r, [?a] ; set value |
IF ~ ?o eq ; advance |
?o ?a, s/8 ; add/sub n |
END IF |
verify |
\} |
match =0 a, ?s v \{ ; r |
@sv t, r, a ; set value |
define ?s 1 |
\} |
verify |
restore ?a, ?o |
} |
;;;;;;;;;;;;;;;; POINTER OPERATION ;;;;;;;;;;;;;;; |
macro let [p] { |
forward |
define ?s 0 |
match =0 (t) \ ; (t) a=*(b) |
a==*(b), ?s p \{ |
@get t, a, [b] |
define ?s 1 |
\} |
match =0 \ ; a=*(b) |
a==*(b), ?s p \{ ; (u8) default |
@get u8, a, [b] |
define ?s 1 |
\} |
match =0 (t) \ ; (t) *(a)=b |
*(a)==b, ?s p \{ |
@set t, b, [a] |
define ?s 1 |
\} |
match =0 \ ; *(a)=b |
*(a)==b, ?s p \{ ; (u8) default |
@set u8, b, [a] |
define ?s 1 |
\} |
match \ |
(t) a==b, p \{ ; (t) a=b |
match *x, a \\{ ; m,m |
match *y, b \\\{ |
@get t, ebx, b ; use ebx |
@set t, ebx, a |
define ?s 1 |
\\\} |
\\} |
IF ?s eq 0 |
match *y, b \\{ ; source=*p |
@get t, a, b |
define ?s 1 |
\\} |
IF ?s eq 0 |
match *x, a \\{ ; destiny=*p |
@set t, b, a |
define ?s 1 |
\\} |
END IF |
END IF |
\} |
match =0 \ |
a==b, ?s p \{ ; a=b |
match *x, a \\{ ; m,m |
match *y, b \\\{ |
@get u8, ebx, b ; use ebx |
@set u8, ebx, a |
define ?s 1 |
\\\} |
\\} |
IF ?s eq 0 |
match *y, b \\{ ; source=* |
@get u8, a, b |
define ?s 1 |
\\} |
IF ?s eq 0 |
match *x, a \\{ ; destiny=*p |
@set u8, b, a |
define ?s 1 |
\\} |
END IF |
END IF |
\} |
; 2-DO: insert improved let |
IF ?s eq 0 ; default |
let p |
END IF |
} |
;;;;;;;;;;;;;;;;;;; FUNCTION ;;;;;;;;;;;;;;;;;;;;; |
macro pushr [p] { ; push parameters backwards |
common ; to access forwards |
IF ~p eq |
reverse |
pushd p |
common |
END IF |
} |
; call a/ddress direct or p/ointer indirect |
macro call a, [p] { |
common pushr p |
call a |
} |
macro callp f, [p] { common call [f], p } |
; call "function" forward reference that |
; has not been defined yet |
macro callf f, [p] { common call !#f, p } |
; call "variadic" procedure with "variable |
; arguments" (...). push invisible # arguments |
; last, call, then adjust esp after |
macro callv f, [p] { |
common ?n=0 |
reverse pushd p |
?n=?n+1 |
common push ?n |
call f |
add esp, (?n+1)*4 |
} |
; call "interface" |
macro callx c, x, [p] { |
common |
pushr p ; push parameters |
mov eax, c |
push eax ; push class address |
mov eax, [eax] |
call dword [eax+x] ; call method offset |
} |
; call function pointer IF non-zero |
macro callfp f { |
cmp dword [f], 0 |
jz @f |
call dword [f] |
@@: |
} |
; call function IF defined |
macro ?call name, [p] { |
common |
IF defined name |
call name, p |
END IF |
} |
; call function then get return. example: |
; get n=text.n t |
; get c=rgb 128, 0, 64 |
macro get [p] { |
common |
define ?s 0 |
match v==f ps, p \{ |
f ps |
mov v, eax |
define ?s 1 |
\} |
match =0 v==f, ?s p \{ |
f |
mov v, eax |
define ?s 1 |
\} |
verify get |
} |
; set label for try/fail |
define ?ef .! ; end function |
macro fault l { define ?ef l } |
macro catch l { define ?ef l } |
; call function then jmp to return |
; if it returns 0. example: |
; try open filename |
; try p=allocate 4*KB |
macro try [p] { |
common |
define ?s 0 |
match a==b, p \{ |
b |
mov a, eax |
define ?s 1 |
\} |
IF ?s eq 0 |
common p |
END IF |
fail ?ef ; endf |
} |
;;;;;;;;;;;;;; FUNCTION/PROCEDURE ;;;;;;;;;;;;;;; |
; create "function/proc/edure"... |
macro function name, [p] { |
common |
local i, n |
n=0 |
forward |
n=n+1 |
common |
!#name#$type='f' |
; only insert this inside of the executable |
; if it was accessed somewhere |
IF used !#name ; real function !name |
!#name: |
; macro to call with no prefix. |
; example: f a, b, c |
macro name p \{ |
pushr p |
call !\#name |
\} |
?begin equ !#name |
?parameters equ p |
?alias equ |
..n.parameters=0 |
..n.locals=0 |
..locals.size=0 |
; create parameter names and offsets |
IF ~ p eq ; if parameters |
virtual at ebp+8 |
forward |
local ..p |
..p dd ? ; (ebp+8)+i*4 |
p equ [..p] |
..n.parameters=\ ; i++ |
..n.parameters+1 |
common |
END virtual |
push ebp ; create stack frame |
mov ebp, esp |
END IF |
; ... |
} |
; HL return statement. use this instead of |
; ret/n in functions. no ret/urn before endf. |
; it inserts one automatically |
macro return v { |
IF ~v eq ; value? |
mov eax, v |
END IF |
IF ..n.parameters<>0 ; if parameters |
mov esp, ebp |
pop ebp |
ret ..n.parameters*4 ; ret n |
ELSE IF ..n.locals<>0 ; if locals |
mov esp, ebp |
pop ebp |
ret |
ELSE |
ret |
END IF |
} |
; end function |
macro endf v { |
IF ~v eq |
mov eax, v |
END IF |
.!: |
return |
.$=$-?begin ; total size |
IF ..n.parameters<>0 ; if parameters |
match p, ?parameters |
\{ restore p, ?begin \} |
END IF |
IF ..n.locals<>0 ; if locals |
match l, local.names |
\{ restore l \} |
match a, ?alias \ |
\{ restore a \} |
fault .! ; reset try label |
END IF |
; end "if used name" at very beginning |
; of function |
END IF |
} |
; aliases for register names inside functions. |
; endf will restore names. example: |
; alias x=r0, y=r1, w=r2, h=r3, c=v1 |
macro alias [x] { |
forward |
syntax 0 |
match name==r, x \{ |
?list.attach ?alias, name |
name equ r |
syntax 1 |
\} |
verify |
} |
; end alias outside function |
macro endal |
{ match a, ?alias \{ restore a \} } |
;;;;;;;;;;;;;;;;;;;;; LOCALS ;;;;;;;;;;;;;;;;;;;;; |
; locals ... - create local 32BIT variables. |
; example: locals x, y, n, c |
macro locals [p] { |
common local.names equ p |
forward ..n.locals=..n.locals+1 |
common ..locals.size=..n.locals*4 |
virtual at ebp-..locals.size |
forward |
local ..l |
..l dd ? |
p equ [..l] |
common |
END virtual |
IF ..n.parameters=0 ; create stack frame? |
push ebp |
mov ebp, esp |
END IF |
sub esp, ..locals.size ; allocate locals |
} |
; create locals of specified sizes or 32BIT. |
; example: |
; locale x, y, username(32), filename(256),\ |
; image(IMAGE.$), my.font(FONT.$), etc |
macro locale [p] { |
common |
..locals.size=0 |
forward ; get names and sizes |
define ?s 0 |
match name(size), p \{ ; size specified |
?list.attach \ |
local.names, name |
verify.size size |
..locals.size=..locals.size+size |
define ?s 1 |
\} |
match =0 name, ?s p \{ ; default 32BIT |
?list.attach \ |
local.names, name |
..locals.size=..locals.size+4 |
define ?s 1 |
\} |
..n.locals=..n.locals+1 |
common |
virtual at ebp-..locals.size ; get offsets |
forward |
local ..l |
define ?s 0 |
match name(size), p \{ |
..l dd (size/4) dup(?) |
name equ [..l] |
define ?s 1 |
\} |
match =0 name, ?s p \{ ; default 32BIT |
..l dd ? |
name equ [..l] |
define ?s 1 |
\} |
common |
END virtual |
IF ..n.parameters=0 ; create stack frame? |
push ebp |
mov ebp, esp |
END IF |
sub esp, ..locals.size ; allocate locals |
} |
;;;;;;;;;;;;;;;;;; IF EXPRESSION ;;;;;;;;;;;;;;;;; |
?NOT equ 0 |
?use.r equ 0 |
; jump if condition to l (or ?NOT IF 1) |
macro jif l, [c] { |
common |
local f |
define ?s 0 |
match =0 =true, ?s c \{ |
test eax, eax |
jz l |
define ?s 1 |
\} |
match =0 =false, ?s c \{ |
test eax, eax |
jnz l |
define ?s 1 |
\} |
match =0 =valid, ?s c \{ |
cmp eax, -1 |
je l |
define ?s 1 |
\} |
match =0 =invalid, ?s c \{ |
cmp eax, -1 |
jne l |
define ?s 1 |
\} |
macro ?J O,A,C,B, [X] \{ |
match =0 X, ?s c \\{ |
IF ?use.r eq 0 |
O A, B ; opcode o1, o2 |
ELSE |
mov ?use.r, A |
O ?use.r, B |
END IF |
IF ?NOT eq 0 |
j\#C l |
ELSE |
jN\#C l |
END IF |
define ?s 1 |
\\} |
\} |
; standard expressions... |
?J cmp,a,NE,b, a<>b ; a not b (a<>b) |
?J cmp,a,BE,b, a<<==b ; a<<=b |
?J cmp,a,AE,b, a>>==b ; a>>=b |
?J cmp,a,B,b, a<<b ; a<<b |
?J cmp,a,A,b, a>>b ; a>>b |
?J cmp,a,LE,b, a<==b ; a<=b |
?J cmp,a,GE,b, a>==b ; a>=b |
?J cmp,a,L,b, a<b ; a<b |
?J cmp,a,G,b, a>b ; a>b |
?J cmp,a,E,b, a==b ; a=b |
?J cmp,a,NE,b, a =not b ; a not b (a<>b) |
?J test,a,NE,b, a&b ; a&b |
?J or,a,NE,b, a|b ; a|b |
?J cmp,a,E,0, =not a ; not a (=0) |
; 2-DO: support pointer arithmetic |
; and functions: if p=allocate 4*KB |
; else, default: a (not 0, by itself) |
?J cmp,a,NE,0,a |
verify 'Invalid expression' c |
?use.r equ 0 |
} |
; jump to l IF NOT condition |
macro jifn l, [c] { |
common |
?NOT equ 1 |
jif l, c |
?NOT equ 0 ; restore default |
} |
; HL IF/ELSE |
macro if.begin { |
local ..start, ..else, ..end |
?IF equ |
?START equ ..start |
?ELSE equ ..else |
?END equ ..end |
?START: |
} |
macro if.n [c] { |
common |
if.begin |
jif ?ELSE, c |
} |
macro if [p] { |
common |
if.begin |
define ?s 0 |
match a=,b, p \{ |
jifn ?ELSE, a |
let b |
define ?s 1 |
\} |
match =0, ?s \{ |
jifn ?ELSE, p |
\} |
verify if |
} |
macro else [p] { |
common |
jmp ?END |
?ELSE: |
restore ?IF |
?IF equ , |
match =,x, p \{ let x \} |
} |
macro else.if [p] { |
common |
local ..else |
jmp ?END |
?ELSE: |
restore ?ELSE |
?ELSE equ ..else |
define ?s 0 |
match a=,b, p \{ |
jifn ?ELSE, a |
. b |
define ?s 1 |
\} |
match =0 a, ?s p \{ |
jifn ?ELSE, a |
\} |
verify else.if |
} |
macro end [p] { |
common |
IF ?IF eq |
?ELSE: |
END IF |
?END: |
restore ?IF, ?START, ?ELSE, ?END |
match =,x, p \{ let x \} |
} |
; call function with parameters then |
; if non/zero |
macro !if f, [p] { |
common f p |
if eax |
} |
macro !if.n f, [p] { |
common f p |
if eax=0 |
} |
jNE equ jne |
jNNE equ je |
jNA equ jna |
jNB equ jnb |
jNG equ jng |
jNL equ jnl |
macro jifc r, c, l { |
test r, r |
j#c l |
} |
macro fail l { |
IF l eq |
jifc eax, z, ?ef |
ELSE |
jifc eax, z, l |
END IF |
} |
macro failn l { |
IF l eq |
cmp eax, -1 |
je ?ef |
ELSE |
cmp eax, -1 |
je l |
END IF |
} |
macro success l { jifc eax, nz, l } |
failnz fix success |
; fail? or escape? on condition |
; example: escape? eax=-1 |
macro fail? [c] { |
common |
IF c eq |
test eax, eax |
jz ?ef |
ELSE |
if c |
jmp ?ef |
end |
END IF |
} |
;;;;;;;;;;;;;;;;;;;;;; LOOP ;;;;;;;;;;;;;;;;;;;;;; |
; loop variations. unfinished... |
macro forever [p] { |
common |
local ..start, ..next, ..end |
?STARTFV equ ..start |
?NEXTFV equ ..next |
?ENDFV equ ..end |
?STARTFV: |
?HL.BLOCK='fv' |
match =,x, p \{ let x \} |
} |
macro endfv [p] { |
common |
?NEXTFV: |
jmp ?STARTFV |
?ENDFV: |
restore ?STARTFV, ?NEXTFV, ?ENDFV |
match a=,b, p \{ let b \} |
} |
macro repeat n { |
local ..start, ..end |
?STARTR equ ..start |
?ENDR equ ..end |
?NR equ n |
?HL.BLOCK='r' |
?STARTR: |
cmp ?NR, 0 |
jle ?ENDR |
} |
macro endr { |
dec ?NR |
jmp ?STARTR |
?ENDR: |
restore ?STARTR, ?ENDR, ?NR |
} |
macro while [c] { |
common |
local ..a, ..b, ..c |
?STARTW equ ..a |
?NEXTW equ ..b |
?ENDW equ ..c |
?HL.BLOCK='w' |
?STARTW: |
define ?s 0 |
match a=,b, c \{ |
jifn ?ENDW, a |
let b |
define ?s 1 |
\} |
match =0 a, ?s c \{ |
jifn ?ENDW, a |
\} |
} |
macro endw [p] { |
common |
?NEXTW: |
jmp ?STARTW |
?ENDW: |
restore ?STARTW, ?NEXTW, ?ENDW |
match =,x, p \{ let x \} |
} |
; unfinished, exhausted, can't keep |
; eyes open... 2-DO: improve all |
; blocks/if/loops |
; loop ; infinite |
; loop n ; # times |
; loop i=0 to n ; iterate (2-DO) |
; loop X, ... ; optional arithmetic |
?LOOP.N fix 1 ; repeat # times |
?LOOP.I fix 2 ; index, i=0 to n |
?LOOP.F fix 3 ; forever, infinite |
macro loop [c] { |
common |
local ..a, ..b, ..c |
?STARTL equ ..a |
?NEXTL equ ..b |
?ENDL equ ..c |
?STARTL: |
define ?s 0 |
match =0 n=,x, ?s c \{ ; loop n, ... |
?HL.BLOCK=?LOOP.N |
?N equ n |
cmp n, 0 |
jle ?ENDL |
let x |
define ?s 1 |
\} |
match =0 =,x, ?s c \{ ; loop, ... |
?HL.BLOCK=?LOOP.F |
let x |
define ?s 1 |
\} |
match =0 n, ?s c \{ ; loop n |
?HL.BLOCK=?LOOP.N |
?N equ n |
cmp n, 0 |
jle ?ENDL |
define ?s 1 |
\} |
verify loop |
} |
macro endl [p] { |
common |
IF ?HL.BLOCK=?LOOP.N |
dec ?N |
restore ?N |
END IF |
?NEXTL: |
jmp ?STARTL |
?ENDL: |
restore ?STARTL, ?NEXTL, ?ENDL |
match =,x, p \{ let x \} |
} |
macro break [p] { |
common |
IF ?HL.BLOCK='fv' |
jmp ?ENDFV |
ELSE IF ?HL.BLOCK='r' |
jmp ?ENDR |
ELSE IF ?HL.BLOCK='w' |
jmp ?ENDW |
ELSE IF ?HL.BLOCK='l' |
jmp ?ENDL |
END IF |
match =,x, p \{ let x \} |
} |
macro next [p] { |
common |
IF ?HL.BLOCK='fv' |
jmp ?STARTFV |
ELSE IF ?HL.BLOCK='r' |
jmp ?STARTR |
ELSE IF ?HL.BLOCK='w' |
jmp ?STARTW |
ELSE IF ?HL.BLOCK='l' |
jmp ?STARTL |
END IF |
match =,x, p \{ let x \} |
} |
macro continue [p] { common next p } |
; 2-DO: create one "end" for all HL blocks |
;;;;;;;;;;;;;;;;;; NEW LANGUAGE ;;;;;;;;;;;;;;;;;; |
; upgrade let with multi-statements. |
; unfinished. 2-DO: create one good "let" |
; with helper macros |
macro let [p] { |
forward |
define ?s 0 |
match =0 \ |
l:, ?s p \{ |
l: |
define ?s 1 |
\} |
match =0 \ |
=go x, ?s p \{ |
jmp x |
define ?s 1 |
\} |
match =0 \ |
=if x, ?s p \{ |
if x |
define ?s 1 |
\} |
match =0 \ |
=return x, ?s p \{ |
return x |
define ?s 1 |
\} |
match =0 \ |
=return, ?s p \{ |
return |
define ?s 1 |
\} |
match =0 \ |
=while x, ?s p \{ |
while x |
define ?s 1 |
\} |
match =0 \ |
=forever x, ?s p \{ |
forever x |
define ?s 1 |
\} |
match =0 \ |
=loop x, ?s p \{ |
loop x |
define ?s 1 |
\} |
match =0 \ |
=end, ?s p \{ |
end |
define ?s 1 |
\} |
match =0 \ |
=endw, ?s p \{ |
endw |
define ?s 1 |
\} |
match =0 \ |
=endl, ?s p \{ |
endl |
define ?s 1 |
\} |
match =0 \ |
=endfv x, ?s p \{ |
endfv |
define ?s 1 |
\} |
match =0 \ |
=break, ?s p \{ |
break |
define ?s 1 |
\} |
match =0 \ |
=next, ?s p \{ |
next |
define ?s 1 |
\} |
IF ?s eq 0 |
let p |
END IF |
} |
macro . [p] { common let p } |
macro go [p] { |
common |
define ?s 0 |
match a=,b, p \{ |
jmp a |
let b |
define ?s 1 |
\} |
match =0, ?s \{ jmp p \} |
} |
/programs/games/codemaster/INCLUDE/MEMORY.INC |
---|
0,0 → 1,274 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ????????????????? MEMORY.INC ??????????????????? |
; allocate n ; see SYSTEM.INC |
; allocate.p p, n |
; destroy p |
; memory.set p, v, n ; 32BIT set/copy/zero |
; memory.copy a, b, n |
; memory.zero p, n |
; get.bit v, n ; get/set/zero bit |
; set.bit v, n |
; zero.bit v, n |
; enable.f v, n ; enable/disable flag |
; disable.f v, n |
; power.2 n ; is power of 2? which one? |
; align.n n, p ; versatile align n to p |
;;;;;;;;;;;;; MEMORY COPY, SET, ZERO ;;;;;;;;;;;;; |
; portable. 32BIT |
function memory.copy, a, b, n |
alias p=r0, q=r1 |
. p=a, q=b, n>>>2 |
loop n, (u32) *p++=*q++, endl |
endf |
function memory.set, a, b, n |
alias p=r0, v=r1, x=r2 |
. p=a, v=b, n>>>2 |
loop n, (u32) *p++=v, endl |
endf |
macro memory.zero p, n { memory.set p, 0, n } |
; x86 specific. aligned |
function memory.copy.x, a, b, n |
push r6 r7 |
. r7=a,\ |
r6=b, r1=n |
test r7, r6 ; address=0? |
jz .e |
cmp r1, 4 ; if n<4 |
jb @f |
push r1 |
shr r1, 2 ; n/4 |
rep movsd ; copy dwords |
pop r1 |
and r1, 3 ; modulo 4 |
jz .e ; remainder? |
@@: |
rep movsb ; copy bytes |
.e: |
pop r7 r6 |
endf |
function memory.set.x, p, v, n |
push r7 |
. r7=p, r0=v,\ |
r0*01010101h,\ |
r1=n |
test r7, r7 ; address=0? |
jz .e |
cmp r1, 4 ; n<4? |
jb @f |
push r1 |
shr r1, 2 |
rep stosd ; copy dwords |
pop r1 |
and r1, 3 ; modulo 4 |
jz .e ; remainder? |
@@: |
rep stosb ; copy bytes |
.e: |
pop r7 |
endf |
;;;;;;;;;;;;;;;; GET/SET/ZERO BIT ;;;;;;;;;;;;;;;; |
; 76543210. warning: r0/r1/r2 cannot be used |
; as parameters. 'v' should be m, 'i' can be m/i |
macro get.bit v, i { ; (v>>i)&1 |
. r0=v, r1=i, r0>>cl, r0&1 |
} |
macro set.bit v, i { ; v|=(1<<i) |
. r0=1, r1=i, r0<<cl, v|r0 |
} |
macro zero.bit v, i { ; v&=~(1<<i) |
. r0=1, r1=i, r0<<cl, not r0, v&r0 |
} |
; 1111.0000 |
macro get.nibble v, i { ; (v>>(i*4))&1111b |
. r0=v, r1=i, r1<<2, r0>>cl, r0&1111b |
} |
macro set.nibble v, i, n { ; v|=(n<<(i*4)) |
. r0=v, r1=i, r2=n, r1<<2, r2<<cl,\ |
r0|r2, v=r0 |
} |
; 33.22.11.00 |
macro get.couple v, i { ; (v>>(i*2))&11b |
. r0=v, r1=i, r1<<1, r0>>cl, r0&11b |
} |
macro set.couple v, i, n { ; v|=(n<<(i*2)) |
. r0=v, r1=i, r2=n, r1<<1, r2<<cl,\ |
r0|r2, v=r0 |
} |
; enable/disable flag |
macro enable.f v, n { . r0=n, v|r0 } |
macro disable.f v, n |
{ . r0=n, not r0, v&r0 } |
macro toggle n { xor n, 1 } ; invert 1/0 |
; create AA.BBB.CCCb/AA.BB.CC.DDb BIT structures |
function triplet, a, b, c |
. r0=a, r0<<6, r1=b, r1<<3, r0|r1, r0|c |
endf |
function quadruplet, a, b, c, d |
. r0=a, r0<<6, r1=b, r1<<4 |
. r2=c, r2<<2, r0|r1, r0|r2, r0|d |
endf |
; reverse byte order |
macro reverse.32 n |
{ . r0=n, bswap r0 } |
macro reverse.24 n |
{ . r0=n, bswap r0, r0>>>8 } |
macro reverse.16 n |
{ . r0=n, cl=al, al=ah, ah=cl } |
;;;;;;;;;;;;;;;;;; POWERS OF 2 ;;;;;;;;;;;;;;;;;;; |
; an unsigned number is a power of 2 if only |
; 1 BIT is set: if !(n&n-1). subtracting 1 |
; inverts all BITs. if n=10000000b (80h/128), |
; n&01111111b=0 |
; to find out which power of 2, search n |
; for 1st 0 BIT from right to left |
; is n power of 2? example: power.2 128 |
; returns 7 |
function power.2, n |
locals i |
. r0=n |
if r0<2, go .r0, end |
. r1=r0, r1-1, r0&r1 |
test r0, r0 |
jnz .r0 |
. n--, i=1 |
@@: |
. r0=1, r1=i, r0<<cl, i++ |
test n, r0 |
jnz @b |
. r0=i, r0-- |
jmp @f |
.r0: . r0=0 |
@@: |
endf |
;;;;;;;;;;;;;;;;;;;;; ALIGN ;;;;;;;;;;;;;;;;;;;;;; |
; versatile align n/umber by power of 2 |
; return n aligned to p in r0. in r1, |
; return the quantity to add to make n |
; divisible by p. algorithm: |
; n+(((p-1)-(n+p-1))&(p-1)) |
function align.n, n, p |
. r1=p, r1-1, r2=n, r2+r1, r0=r1 |
. r0-r2, r0&r1, r1=r0, r2=n, r0+r2 |
endf |
;;;;;;;;;;;;;;;; SOURCE, DESTINY ;;;;;;;;;;;;;;;;; |
align |
void source, destiny |
integer origin, omega |
function create.source, size |
destroy source |
try source=allocate size |
memory.zero source, size |
. origin=0, omega=0 |
endf 1 |
function create.destiny, size |
destroy destiny |
try destiny=allocate size |
memory.zero destiny, size |
. origin=0, omega=0 |
endf 1 |
;;;;;;;;;;;;;;;;;;; TESTING... ;;;;;;;;;;;;;;;;;;; |
; optimized 128-BIT copy/set. ".fast"=CPU |
; specific, but they do not replace the |
; portable algorithms |
; address p must be aligned by 16 (movaps) and |
; size n must be divisible by 16. v/alue must |
; be 32BIT or use 1/2 macros to expand |
function memory.set.fast, p, v, n |
. r0=p, r2=v, r1=n,\ ; start at end |
r0+r1, neg r1 ; negate index |
movd xmm0, r2 |
pshufd xmm0, xmm0, 0 ; duplicate dwords |
@@: |
movaps [r0+r1], xmm0 |
add r1, 16 |
jnz @b |
endf |
macro memory.set.2.fast p, v, n { |
. r0=v, r0*00010001h |
memory.set.fast p, r0, n |
} |
macro memory.set.1.fast p, v, n { |
. r0=v, r0*01010101h |
memory.set.fast p, r0, n |
} |
; destiny a/ddress must be aligned by 16 and |
; size n must be divisible by 16 |
function memory.copy.fast.a, a, b, n |
. r0=a, r2=b, r1=n,\ |
r0+r1, r2+r1, neg r1 |
@@: |
movaps xmm0, [r2+r1] |
movaps [r0+r1], xmm0 |
add r1, 16 |
jnz @b |
endf |
; unaligned... |
function memory.copy.fast, a, b, n |
. r0=a, r2=b, r1=n,\ |
r0+r1, r2+r1, neg r1 |
@@: |
movups xmm0, [r2+r1] |
movups [r0+r1], xmm0 |
add r1, 16 |
jnz @b |
endf |
/programs/games/codemaster/INCLUDE/SYSTEM.INC |
---|
0,0 → 1,956 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ????????????????? SYSTEM.INC ??????????????????? |
;;;;;;;;;;;;;;;;;;;;; IMPORT ;;;;;;;;;;;;;;;;;;;;; |
; RVAs of dll names and tables, ending with 20 |
; zero bytes |
macro library [names] { |
forward dd 0,0,0,\ |
RVA names#_name, RVA names#_table |
common dd 0,0,0,0,0 |
} |
; DLL name + import RVA table. each table ends with 0. |
; finally, import names. dw 0 is "ordinal" (N/A) |
macro import name, [names] { |
common |
name#_name \ ; text DLL_name='DLL.DLL' |
db `name#'.DLL', 0 |
name#_table: ; DLL_table: |
forward |
IF used !#names |
!#names dd RVA _#names ; import name RVAs |
macro names [p] \{ ; call with no |
\common ; invoke prefix |
pushr p |
call [!#names] |
\} |
END IF |
common dd 0 ; end |
forward |
IF used !#names |
_#names dw 0 ; import names |
db `names, 0 ; 'import' |
END IF |
} |
;;;;;;;;;;;;;;;;;;;; IMPORTS ;;;;;;;;;;;;;;;;;;;;; |
data import |
library MSVCRT, KERNEL32, USER32, SHELL32,\ |
GDI32, COMDLG32 |
import MSVCRT, sprintf |
import KERNEL32,\ |
ExitProcess, GetCommandLineA,\ |
HeapCreate, HeapAlloc, HeapReAlloc, HeapSize,\ |
HeapFree, HeapDestroy, VirtualAlloc, VirtualFree,\ |
GetModuleHandleA, GetModuleFileNameA,\ |
CreateFileA, GetFileSize, ReadFile, WriteFile,\ |
SetFilePointer, CloseHandle, CopyFileA,\ |
MoveFileA, DeleteFileA, GetTickCount,\ |
GetSystemTime, GetLocalTime, GetFileTime,\ |
FileTimeToSystemTime, SystemTimeToFileTime,\ |
FileTimeToLocalFileTime,\ |
SystemTimeToTzSpecificLocalTime,\ |
GetFileAttributesExA, CompareFileTimeA,\ |
GetCurrentDirectoryA, SetCurrentDirectoryA,\ |
CreateDirectoryA, LoadLibraryA, FreeLibrary,\ |
GetProcAddress, FindFirstFileA, FindNextFileA,\ |
FindClose, WaitForSingleObject, Sleep |
import USER32,\ |
GetDC, ReleaseDC,\ |
MessageBoxA, RegisterClassExA, CreateWindowExA,\ |
DestroyWindow, ShowWindow, MoveWindow,\ |
UpdateWindow, GetMessageA, PeekMessageA,\ |
TranslateMessage, DispatchMessageA,\ |
SendMessageA, DefWindowProcA, PostQuitMessage,\ |
WaitMessage, GetAsyncKeyState, LoadImageA,\ |
LoadIconA, LoadCursorA, SetCursor, ShowCursor,\ |
SetCursorPos, OpenClipboard, SetClipboardData,\ |
IsClipboardFormatAvailable, GetClipboardData,\ |
CloseClipboard, EmptyClipboard,\ |
GetSystemMetrics, BeginPaint, EndPaint,\ |
FillRect, InvalidateRect, SetTimer |
import SHELL32, ShellExecuteA, ShellExecuteExA |
import GDI32, SelectObject, DeleteObject,\ |
GetObjectA, DeleteDC, TextOutA, CreateFontA,\ |
CreateFontIndirectA, SetDIBits, BitBlt, StretchBlt,\ |
CreateBitmap, CreateCompatibleDC |
import COMDLG32, GetOpenFileNameA,\ |
GetSaveFileNameA, ChooseColorA, ChooseFontA |
END data |
;;;;;;;;;;;;;;;;;;;;; SYSTEM ;;;;;;;;;;;;;;;;;;;;; |
align |
void @module, @heap |
void directory, file.name, command.line |
?t equ directory |
;;;;;;;;;;;;;;;;;;;; MINIMAL ;;;;;;;;;;;;;;;;;;;;; |
; say t - display message |
; say t, m - title and message |
; say.n n - number |
; examples: |
; say 'Hi' |
; say name |
; say.n 123 |
macro os.say t, m { MessageBoxA 0, m, t, 0 } |
macro os.ask q, t { MessageBoxA, 0, q, t, 3 } |
function _say, t, m |
os.say t, m |
endf |
macro say a, b { |
pusha |
IF a eqtype '' |
make.txt r0, a |
ELSE |
. r0=a |
END IF |
IF b eq |
_say r0, r0 |
ELSE |
IF b eqtype '' |
make.txt r2, b |
ELSE |
. r2=b |
END IF |
_say r2, r0 |
END IF |
popa |
} |
function say.n, n |
locale t(32) |
pusha |
. r1=&t |
u2t n, r1 |
. r1=&t |
_say r1, r1 |
popa |
endf |
function say.h, n |
locale t(32) |
pusha |
. r1=&t |
h2t n, r1 |
. r1=&t |
_say r1, r1 |
popa |
endf |
function say.b, n |
locale t(32) |
pusha |
. r1=&t |
b2t n, r1 |
. r1=&t |
_say r1, r1 |
popa |
endf |
macro sayz t { |
say ?LITERALS+?literals.i |
?literal t |
} |
macro ask q, t { os.ask q, t } |
macro cinvoke proc,[arg] |
{ common |
size@ccall = 0 |
IF ~ arg eq |
reverse |
pushd arg |
size@ccall = size@ccall+4 |
common |
END IF |
call [proc] |
IF size@ccall |
add esp,size@ccall |
END IF } |
macro sprintf t, f, [p] { |
common |
cinvoke !sprintf, t, f, p |
} |
;;;;;;;;;;;;;;;;;;;;; DEBUG ;;;;;;;;;;;;;;;;;;;;;; |
bug.t db 'BUG', 0 |
macro bug { say bug.t } |
macro bug.x t { |
log t |
execute log.file |
exit |
} |
macro BUG { db 0CCh } ; int3 breakpoint |
;;;;;;;;;;;;;;;;;;;; MEMORY ;;;;;;;;;;;;;;;;;;;;;; |
macro os.memory |
{ get @heap=HeapCreate 0, 0, 0 } |
macro os.allocate n { HeapAlloc @heap, 0, n } |
macro os.reallocate p, n |
{ HeapReAlloc @heap, 0, p, n } |
macro os.destroy p { HeapFree @heap, 0, p } |
;;;;;;;;;;;;;;; ALLOCATE, DESTROY ;;;;;;;;;;;;;;;; |
; allocate n |
; allocate.p &p, n |
; destroy &p |
; example: try p=allocate 4*KB |
function allocate, n |
os.allocate n |
endf |
function allocate.p, p, n |
if p=0 |
allocate n |
return |
end |
os.reallocate p, n |
endf |
function destroy, p |
if p |
os.destroy p |
end |
endf |
macro destroy [p] { forward destroy p } |
;;;;;;;;;;;;;;;;;;;;; TIME ;;;;;;;;;;;;;;;;;;;;;;; |
FILE.TIME fix u64 |
macro os.get.time { |
GetLocalTime local.time |
update.time local.time |
} |
function os.delay, ms |
locals start |
get start=GetTickCount |
@@: |
GetTickCount |
. r1=start, r1+ms |
cmp r0, r1 |
jb @b |
endf |
get.clock fix GetTickCount |
;;;;;;;;;;;;;;;;;;;;; RANDOM ;;;;;;;;;;;;;;;;;;;;; |
align integer @seed |
; generate unique random number: 0-n |
; seed=(seed*343FDh)+269EC3h |
; seed=((seed>>16)&7FFFh)/(n+1) |
function random, n |
. r0=@seed |
if false ; initialize seed |
rdtsc ; read date/time stamp counter |
. @seed=r0 |
end |
. r0*343FDh, r0+269EC3h,\ |
@seed=r0, r0>>16, r0&7FFFh,\ |
r1=n, r1+1, r0/r1, r0=r2 |
endf |
; random(from-to-2)+from |
function random.x, from, to |
. r0=from, r0-to, r0-2 |
random r0 |
. r0+from |
endf |
;;;;;;;;;;;;;;;;;;; FILE I/O ;;;;;;;;;;;;;;;;;;;;; |
numeric EOF=-1,\ |
CREATE_NEW=1, CREATE_ALWAYS, OPEN_EXISTING,\ |
OPEN_ALWAYS, TRUNCATE_EXISTING,\ |
GENERIC_READ=80000000h, GENERIC_WRITE=40000000h,\ |
FILE_SHARE_READ=1, FILE_SHARE_WRITE,\ |
FILE_ATTRIBUTE_NORMAL=80h,\ |
SEEK.BEGIN=0, SEEK.SET, SEEK.END |
;;;;;;;;;;;;;;;;; CURRENT FILE ;;;;;;;;;;;;;;;;;;; |
align |
void file.p ; pointer for load/save |
integer file.h,\ ; handle |
file.n64, file.n ; size 64:32 |
integer tmp.rw |
macro flush { destroy file.p } |
; return handle or -1 if error |
function os.create.file, file, access, share,\ |
security, action, attributes, template |
call !text.copy, file.name, file |
CreateFileA file.name, access, share,\ |
security, action, attributes, template |
. file.h=r0 |
endf |
macro os.open file { |
os.create.file file, GENERIC_READ \ |
or GENERIC_WRITE, FILE_SHARE_READ,\ |
0, OPEN_EXISTING, 0, 0 |
} |
macro os.create file { |
os.create.file file, GENERIC_WRITE,\ |
0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 |
} |
macro os.seek n, r |
{ SetFilePointer file.h, n, 0, r } |
macro os.read p, n { |
. r0=&tmp.rw |
ReadFile file.h, p, n, r0, 0 |
} |
macro os.write p, n { |
. r0=&tmp.rw |
WriteFile file.h, p, n, r0, 0 |
} |
macro os.get.file.size { GetFileSize file.h, 0 } |
macro os.close { CloseHandle file.h } |
;;;;;;;;;;;;;;; COPY, MOVE, DELETE ;;;;;;;;;;;;;;; |
macro copy.file a, b, r { CopyFileA a, b, r } |
macro move.file a, b { MoveFileA a, b } |
macro delete.file f { DeleteFileA f } |
macro rename.file a, b { os.move.file a, b } |
;;;;;;;;;;;;;;;;;; DIRECTORIES ;;;;;;;;;;;;;;;;;;; |
macro os.get.directory |
{ GetCurrentDirectoryA 256, directory } |
macro os.set.directory f |
{ SetCurrentDirectoryA f } |
macro os.create.directory f |
{ CreateDirectoryA f, 0 } |
macro os.get.file.name |
{ GetModuleFileNameA 0, directory, 1*KB } |
macro os.get.command.line { GetCommandLineA } |
;;;;;;;;;;;;;;;;;;;; EXECUTE ;;;;;;;;;;;;;;;;;;;;; |
macro execute file |
{ ShellExecuteA 0, 0, file, 0, 0, 3 } |
;;;;;;;;;;;;;;;;;; FIND FILES ;;;;;;;;;;;;;;;;;;;; |
macro os.find.data { |
BLOCK find.data(338) ; WIN32_FIND_DATA |
os.found.file equ find.data+44 |
} |
macro os.find.first file |
{ FindFirstFileA file, find.data } |
macro os.find.next |
{ FindNextFileA find.data.h, find.data } |
macro os.find.end { FindClose find.data.h } |
;;;;;;;;;;;;;;;;;;;;; REDRAW ;;;;;;;;;;;;;;;;;;;;; |
macro create.blank.screen w, h { |
create.vga os.w, os.h, WHITE ; 0 |
create.blank.window w, h |
} |
macro redraw { |
calle draw |
} |
macro render b { |
; call !clear.screen |
IF b eq |
redraw |
END IF |
IF used cursor |
call !draw.cursor, cursor |
END IF |
IF b eq |
call !show.vga |
ELSE |
copy.box box, b |
call !show.vga.box |
END IF |
} |
;;;;;;;;;;;;;;;;;;;; WINDOZE ;;;;;;;;;;;;;;;;;;;;; |
macro POINT [a] { a: integer a#.x, a#.y } |
macro RECT [a] { a: integer a#.left,\ |
a#.top, a#.right, a#.bottom } |
macro MSG [a] { |
a: integer a#.hwnd, a#.message,\ |
a#.wParam, a#.lParam, a#.time |
POINT a#.pt |
} |
macro WNDCLASSEX [a] { |
a: integer a#.cbSize=48,\ |
a#.style, a#.lpfnWndProc, a#.cbClsExtra,\ |
a#.cbWndExtra, a#.hInstance, a#.hIcon,\ |
a#.hCursor, a#.hbrBackground,\ |
a#.lpszMenuName, a#.lpszClassName, a#.hIconSm |
WNDCLASSEX.$=$-a |
} |
macro PAINTSTRUCT [a] { |
a: integer a#.hdc, a#.fErase |
RECT a#.rcPaint |
integer a#.fRestore, a#.fIncUpdate |
text a#.rgbReserved(32) |
} |
macro BITMAP [a] { |
a: integer a#.bmType,\ |
a#.bmWidth, a#.bmHeight, a#.bmWidthBytes |
short a#.bmPlanes, a#.bmBitsPixel |
void a#.bmBits |
BITMAP.$=$-a |
} |
macro BITMAPINFOHEADER [a] { |
a: integer a#.biSize, a#.biWidth, a#.biHeight |
short a#.biPlanes, a#.biBitCount |
integer a#.biCompression, a#.biSizeImage,\ |
a#.biXPelsPerMeter, a#.biYPelsPerMeter,\ |
a#.biClrUsed, a#.biClrImportant |
BITMAPINFOHEADER.$=$-a |
} |
macro BITMAPINFO [a] { |
BITMAPINFOHEADER a |
integer bmiColors |
BITMAPINFO.$=BITMAPINFOHEADER.$+4 |
} |
; window messages |
numeric WM_*, \ |
CREATE=1, DESTROY=2, MOVE=3, SIZE=5,\ |
SETFOCUS=7, KILLFOCUS=8, GETTEXT=0Dh,\ |
SETTEXT=0Ch, GETTEXTLENGTH=0Eh,\ |
PAINT=0Fh, CLOSE=10h, QUIT=12h, CUT=300h,\ |
COPY=301h, PASTE=302h, CLEAR=303h,\ |
SETFONT=30h, COMMAND=111h, TIMER=0113h |
; window styles |
numeric WS_*, \ |
POPUP=80000000h, MINIMIZE=20000000h,\ |
VISIBLE=10000000h, MAXIMIZE=1000000h,\ |
CAPTION=0C00000h, BORDER=800000h,\ |
DLGFRAME=400000h, VSCROLL=200000h,\ |
HSCROLL=100000h, SYSMENU=80000h,\ |
THICKFRAME=40000h, MINIMIZEBOX=20000h,\ |
MAXIMIZEBOX=10000h |
WS_BLANK = WS_VISIBLE+WS_POPUP |
WS_DEFAULT = WS_VISIBLE+WS_CAPTION+\ |
WS_MINIMIZEBOX+WS_SYSMENU |
CS_DBLCLKS=8 |
; keyboard+mouse messages |
numeric WM_*,\ |
KEYDOWN=100h, KEYUP, CHAR, DEADCHAR,\ |
SYSKEYDOWN, SYSKEYUP, SYSCHAR |
numeric WM_*,\ |
MOUSEMOVE=200h, LBUTTONDOWN, LBUTTONUP,\ |
LBUTTONDBLCLK, RBUTTONDOWN, RBUTTONUP,\ |
RBUTTONDBLCLK, MBUTTONDOWN, MBUTTONUP,\ |
MBUTTONDBLCLK, MOUSEWHEEL |
; virtual key codes. function keys=(6Fh+N). |
; example: F1=70h (6Fh+1) |
numeric K.*,\ |
FUNCTION=6Fh, LEFT=25h, UP=26h, RIGHT=27h,\ |
DOWN=28h, ESCAPE=1Bh, SPACE=20h, DELETE=2Eh,\ |
CONTROL=11h, LCONTROL=0A2h, RCONTROL=0A3h,\ |
LALT=0A4h, RALT=0A5h, BACK=8, TAB=9,\ |
RETURN=0Dh, END=23h, HOME=24h,\ |
A='A', S='S', D='D', W='W' |
SRCCOPY=00CC0020h |
macro os.show.cursor { ShowCursor 1 } |
;;;;;;;;;;;;;;;;;;;;; SYSTEM ;;;;;;;;;;;;;;;;;;;;; |
align |
integer os.w, os.h, os.bpp |
void _hwnd ; handle |
void _dc ; device context |
void _mdc ; memory dc |
WNDCLASSEX _wc ; window |
MSG _wm ; message |
PAINTSTRUCT _ps ; for PAINT |
BITMAP _bm ; for draw.bitmap.w |
void vga.hbm |
BITMAPINFO vga.bmi |
RECT vga.rect |
text _cn='WC', _wt='' ; classname, title |
;;;;;;;;;;;;;;;;; CREATE WINDOW ;;;;;;;;;;;;;;;;;; |
function create.window.x, style, procedure,\ |
w, h, title, class.name |
locals x, y |
. _wc.cbSize=WNDCLASSEX.$ |
. _wc.hInstance=@module |
. _wc.lpfnWndProc=procedure |
. _wc.lpszClassName=class.name |
. _wc.style=CS_DBLCLKS, _wc.hbrBackground=8 |
get _wc.hIcon=LoadIconA 0, 7F00h |
get _wc.hCursor=LoadCursorA 0, 7F00h |
try RegisterClassExA _wc |
. r0=os.w, r0>>1, r2=w, r2>>1, r0-r2, x=r0 |
. r0=os.h, r0>>1, r2=h, r2>>1, r0-r2, y=r0 |
try _hwnd=CreateWindowExA 0, class.name,\ |
title, style, x, y, w, h, 0, 0, @module, 0 |
endf 1 |
macro create.blank.window w, h { |
create.window.x WS_BLANK, !_window.procedure,\ |
w, h, _wt, _wc |
} |
macro create.default.window title { |
create.window.x WS_DEFAULT, !_window.procedure,\ |
os.w, os.h, title, _wc |
} |
;;;;;;;;;;;;;;;;;; MESSAGE LOOP ;;;;;;;;;;;;;;;;;; |
macro begin.message.loop { |
.begin.ml: |
GetMessageA _wm, 0, 0, 0 |
fail .end.ml |
TranslateMessage _wm |
DispatchMessageA _wm |
} |
macro end.message.loop { |
go .begin.ml |
.end.ml: |
. r0=_wm.wParam |
} |
macro message.loop { |
begin.message.loop |
end.message.loop |
} |
macro process.messages { |
.begin.ml: |
PeekMessageA _wm, 0, 0, 0, 0 |
fail .no.message |
GetMessageA _wm, 0, 0, 0 |
fail .end.ml |
TranslateMessage _wm |
DispatchMessageA _wm |
go .begin.ml |
.no.message: |
} |
macro end.messages { |
go .begin.ml |
.end.ml: |
ExitProcess _wm.wParam |
} |
macro minimize.window { ShowWindow _hwnd, 6 } |
;;;;;;;;;;;;;;;;;;;;;; INPUT ;;;;;;;;;;;;;;;;;;;;; |
align 4 |
integer event.id, key.event, mouse.event,\ |
key, any.key, key.c, exit.if.esc=YES,\ |
mouse.1, mouse.2, mouse.x, mouse.y,\ |
mouse.px, mouse.py, mouse.double, mouse.wheel,\ |
mouse.drag, mouse.drag.x, mouse.drag.y,\ |
mouse.drop, mouse.drop.x, mouse.drop.y |
macro os.key.state k { GetAsyncKeyState k } |
macro os.set.cursor.xy x, y |
{ SetCursorPos x, y } |
function key.state, k |
os.key.state k |
endf |
; if key state |
macro if.key k { !if key.state K.#k } |
macro if.not.keys k { !if.n key.state K.#k } |
function select.box, box |
. r0=mouse.x, r1=mouse.y |
IF defined cursor |
. r0+cursor.spot.x, r1+cursor.spot.y |
END IF |
call !point.inside, box, r0, r1 |
endf |
macro if.select box { !if select.box, box } |
macro else.if.select box |
{ !else.if select.box, box } |
macro if.not.select box |
{ !if.n select.box, box } |
macro if.click box { |
select.box box |
and r0, mouse.1 |
if true |
} |
;;;;;;;;;;;;;;;;;;;;; EVENTS ;;;;;;;;;;;;;;;;;;;;; |
align |
void !_on.event, !on.main,\ |
!_on.create, !_on.destroy, !_on.close,\ |
!_on.draw, !_on.game, !_on.command,\ |
!_on.key, !_on.mouse, !_on.timer, !_on.exit |
macro define.events [e] |
{ mov [!!_on.#e], !on.#e } |
macro calle e { |
if dword [!!_on.#e] |
call dword [!!_on.#e] |
end |
} |
!call fix calle |
macro !on name { function on.#name } |
macro !end { endf 1 } |
;;;;;;;;;;;;;;;;;;;;; TIMER ;;;;;;;;;;;;;;;;;;;;;; |
macro os.set.timer f, ms |
{ SetTimer _hwnd, 1, ms, f } |
macro set.timer a, b { |
IF b eq |
os.set.timer !on.timer, a |
ELSE |
os.set.timer a, b |
END IF |
} |
;;;;;;;;;;;;;;;; WINDOW PROCEDURE ;;;;;;;;;;;;;;;; |
function _window.procedure, window, message, wp, lp |
alias m=r0 |
. m=message, event.id=0, mouse.double=0 |
if m=WM_PAINT |
get _dc=BeginPaint _hwnd, _ps |
render |
EndPaint _hwnd, _ps |
go .default |
else.if m=WM_COMMAND |
calle command |
else.if m=WM_KEYDOWN |
. key=wp, event.id='k', key.event='k' |
if exit.if.esc |
if wp=K.ESCAPE |
SendMessageA window, WM_DESTROY, 0, 0 |
end |
end |
.key: |
calle key |
return 0 |
else.if m=WM_KEYUP |
. key=NO, event.id='k', key.event='r' |
go .key |
else.if m=WM_CHAR |
. key=wp, event.id='k', key.event='c' |
go .key |
else.if m=WM_MOUSEMOVE |
. mouse.event='m' |
if mouse.1 |
if not mouse.drag |
. mouse.drag=YES,\ |
mouse.drag.x=mouse.x,\ |
mouse.drag.y=mouse.y |
end |
end |
.mouse: |
. event.id='m', r0=lp, r1=r0,\ |
r0&0FFFFh, mouse.x=r0,\ |
r1>>16, r1&0FFFFh, mouse.y=r1 |
calle mouse |
if mouse.event='m' |
. mouse.px=mouse.x,\ |
mouse.py=mouse.y |
end |
return 0 |
else.if m=WM_LBUTTONDOWN |
. mouse.event='c', mouse.1=YES,\ |
mouse.drop=NO |
go .mouse |
else.if m=WM_LBUTTONUP |
. mouse.event='r', mouse.1=NO |
if mouse.drag |
. mouse.drop=YES,\ |
mouse.drop.x=mouse.x,\ |
mouse.drop.y=mouse.y,\ |
mouse.drag=NO |
end |
go .mouse |
else.if m=WM_LBUTTONDBLCLK |
. mouse.double=YES |
go .mouse |
else.if m=WM_RBUTTONDOWN |
. mouse.event='rc', mouse.2=YES |
go .mouse |
else.if m=WM_RBUTTONUP |
. mouse.event='rr', mouse.2=NO |
go .mouse |
else.if m=WM_MOUSEWHEEL |
. mouse.event='w', r1=wp,\ |
r1>>16, mouse.wheel=r1 |
go .mouse |
else.if m=WM_CREATE |
calle create |
go .default |
else.if m=WM_DESTROY |
.destroy: |
calle destroy |
PostQuitMessage 0 |
end |
.default: DefWindowProcA \ |
window, message, wp, lp |
endf |
;;;;;;;;;;;;;;; LOAD/DRAW H/BITMAP ;;;;;;;;;;;;;;; |
function load.bitmap.w, file |
locals p |
try p=LoadImageA @module, file, 0, 0, 0, 10h |
GetObjectA p, BITMAP.$, _bm |
endf p |
function draw.bitmap.w, hbmp, x, y, w, h |
locals bmw, bmh |
GetObjectA hbmp, BITMAP.$, _bm |
. bmw=_bm.bmWidth, bmh=_bm.bmHeight |
get _mdc=CreateCompatibleDC _dc |
SelectObject _mdc, hbmp |
StretchBlt _dc, x, y, w, h,\ |
_mdc, 0, 0, bmw, bmh, SRCCOPY |
DeleteDC _mdc |
endf |
;;;;;;;;;;;;;;;;;;;;;; VGA ;;;;;;;;;;;;;;;;;;;;;;; |
macro os.get.screen.w |
{ get os.w=GetSystemMetrics 0 } |
macro os.get.screen.h |
{ get os.h=GetSystemMetrics 1 } |
function os.create.vga, w, h |
alias p=r0, x=r1 |
; set.screen screen.w, screen.h, screen.bpp |
try vga.hbm=CreateBitmap \ |
screen.w, screen.h, 32, 1, vga.p |
memory.zero vga.bmi, BITMAPINFOHEADER.$ |
. vga.bmi.biSize=BITMAPINFOHEADER.$ |
. vga.bmi.biWidth=screen.w |
. x=screen.h, neg x, vga.bmi.biHeight=x |
. vga.bmi.biPlanes=1, vga.bmi.biBitCount=32 |
endf |
function os.show.vga |
SetDIBits _dc, vga.hbm, 0, screen.h,\ |
vga.p, vga.bmi, 0 |
draw.bitmap.w vga.hbm, 0, 0, screen.w, screen.h |
. vga.rect.left=0, vga.rect.top=0,\ |
vga.rect.right=screen.w,\ |
vga.rect.bottom=screen.h |
InvalidateRect _hwnd, vga.rect, 0 |
endf |
function show.vga.box |
SetDIBits _dc, vga.hbm, 0, screen.h,\ |
vga.p, vga.bmi, 0 |
draw.bitmap.w vga.hbm,\ |
box.x, box.y, box.w, box.y |
. r0=box.x, r1=box.y,\ |
vga.rect.left=r0, vga.rect.top=r1,\ |
r0+box.w, vga.rect.right=r0,\ |
r1+box.h, vga.rect.bottom=r1 |
InvalidateRect _hwnd, vga.rect, 0 |
endf |
macro show.vga.box b { |
IF ~b eq |
copy.box box, b |
END IF |
show.vga.box |
} |
macro define.vga { os.define.vga } |
; create vga/buffer for drawing |
function create.vga, w, h, c |
if vga.p=0, r0=w, r0*h, r0<<2 |
try vga.p=allocate r0 |
end |
call !clear.screen, c |
os.create.vga w, h |
endf 1 |
function show.vga |
os.show.vga |
endf |
function set.vga, w, h |
os.set.vga |
endf |
function end.vga |
destroy vga |
os.end.vga |
endf |
;;;;;;;;;;;;;;;;;; ENTER+EXIT ;;;;;;;;;;;;;;;;;;;; |
; user-defined enter/exit routines will be called |
; if defined/nonzero |
function os.enter |
try @module=GetModuleHandleA 0 |
try @heap=HeapCreate 0, 0, 0 |
try directory=allocate 1*KB |
. r0=directory, *r0=0 |
try file.name=allocate 1*KB |
. r0=file.name, *r0=0 |
os.get.directory |
os.get.command.line |
. command.line=r0 |
endf 1 |
function exit |
ExitProcess 0 |
endf |
;;;;;;;;;;;;; EXECUTABLE STRUCTURE ;;;;;;;;;;;;;;; |
align |
section '.one' \ |
code readable writable executable |
!main: |
os.enter |
if false |
say 'System error' |
exit |
end |
call !main! |
exit |
ret |
function main! |
os.get.screen.w |
os.get.screen.h |
set.screen WINDOW.W, WINDOW.H, 32 |
try create.vga screen.w, screen.h, BLACK |
define.events create, draw, key, mouse |
create.blank.window screen.w, screen.h |
os.show.cursor |
message.loop |
endf |
align |
/programs/games/codemaster/INCLUDE/SYSTEMK.INC |
---|
0,0 → 1,231 |
;;;;;;;;;;;;;;;;;;;;; SYSTEM ;;;;;;;;;;;;;;;;;;;;; |
; menuet interrupt: eax, ebx, ecx, edx |
macro mint a, b, c, d { |
IF ~a eq |
. r0=a |
END IF |
IF ~b eq |
. r3=b |
END IF |
IF ~c eq |
. r1=c |
END IF |
IF ~d eq |
. r2=d |
END IF |
db 0CDh, 40h |
} |
; events |
EVENT.REDRAW=1 |
EVENT.KEY=2 |
EVENT.BUTTON=3 |
align |
integer timer.speed=-1,\ |
timer.counter, event.delay=1 |
macro set.timer n { |
. r0=n, r1=10, r0/r1 |
. timer.speed=r0, timer.counter=r0 |
} |
macro get.timer { mint 26, 9 } |
macro delay x { |
. r0=x, r0/100, r3=r0 |
mint 5 |
} |
macro wait.event { mint 23, event.delay } |
;;;;;;;;;;;;;;;;;;;;; WINDOW ;;;;;;;;;;;;;;;;;;;;; |
function draw.window |
. r2=0, r6=0, r7=0FFFFFFh |
. r3=WINDOW.X, r3<<16, r3|screen.w |
. r1=WINDOW.Y, r1<<16, r1|screen.h |
mint 0 |
endf |
macro draw.begin { mint 12, 1 } |
macro draw.end { mint 12, 2 } |
macro render { call !on.draw } ; mint 15, 3 |
macro retrace { mint 18, 14 } |
;;;;;;;;;;;;;;;;;;;;; INPUT ;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
align |
integer event.type |
integer key, old.key, key.event |
text keys.t(128) |
numeric KEY.ESCAPE=27, KEY.SPACE=' ',\ |
KEY.UP=0B2h, KEY.RIGHT=0B3h, KEY.DOWN=0B1h,\ |
KEY.LEFT=0B0h, KEY.A='a', KEY.S='s',\ |
KEY.D='d', KEY.W='w' |
macro get.key.buffer { mint 26, 2, 1, keys.t } |
integer mouse.event,\ |
mouse.1, mouse.2, mouse.x, mouse.y,\ |
mouse.drag, mouse.drag.x, mouse.drag.y,\ |
mouse.drop, mouse.drop.x, mouse.drop.y,\ |
old.mouse.1, old.mouse.2,\ |
old.mouse.x, old.mouse.y |
macro get.mouse.xy { mint 37, 0 } |
macro get.mouse.buttons { mint 37, 2 } |
macro get.mouse.wheel { mint 37, 3 } |
function update.mouse |
. mouse.event=0 |
. old.mouse.1=mouse.1, old.mouse.2=mouse.2 |
. old.mouse.x=mouse.x, old.mouse.y=mouse.y |
get.mouse.xy |
. r1=r0, r1&0FFFFh, r0>>>16, r0&0FFFFh |
. mouse.x=r0, mouse.y=r1 |
get.mouse.buttons |
. r1=r0, r1&1, mouse.1=r1 |
. r1=r0, r1&2, mouse.2=r1 |
if mouse.1 |
if not old.mouse.1, mouse.event='c' |
. mouse.drop=NO |
callf on.mouse |
return 1 |
end |
else.if old.mouse.1, mouse.event='r' |
callf on.mouse |
if mouse.drag |
. mouse.drop=YES,\ |
mouse.drop.x=mouse.x,\ |
mouse.drop.y=mouse.y,\ |
mouse.drag=NO |
. mouse.event='d' |
callf on.mouse |
end |
return 1 |
end |
. r0=mouse.x, r1=old.mouse.x |
if r0<>r1 |
.mouse.move: |
. mouse.event='m' |
callf on.mouse |
if mouse.1 |
if not mouse.drag |
. mouse.drag=YES,\ |
mouse.drag.x=mouse.x,\ |
mouse.drag.y=mouse.y |
end |
else |
. mouse.drop=NO |
end |
return 1 |
else |
. r0=mouse.y, r1=old.mouse.y |
if r0<>r1 |
go .mouse.move |
end |
end |
endf 0 |
function select.box, box |
. r0=mouse.x, r1=mouse.y |
. r0-WINDOW.X, r1-WINDOW.Y |
callf point.inside, box, r0, r1 |
endf |
macro if.select box { !if select.box, box } |
macro else.if.select box |
{ !else.if select.box, box } |
;;;;;;;;;;;;;;;;;;;;; RANDOM ;;;;;;;;;;;;;;;;;;;;; |
align integer @seed |
; generate unique random number: 0-n |
function random, n |
. r0=@seed |
if false |
rdtsc |
. @seed=r0 |
end |
. r0*343FDh, r0+269EC3h,\ |
@seed=r0, r0>>16, r0&7FFFh,\ |
r1=n, r1+1, r0/r1, r0=r2 |
endf |
; random(from-to-2)+from |
function random.x, from, to |
. r0=from, r0-to, r0-2 |
random r0 |
. r0+from |
endf |
;;;;;;;;;;;;;;;;;;;;;; MAIN ;;;;;;;;;;;;;;;;;;;;;; |
; main entry. detect current input states, |
; translate and redirect to on.event handlers. |
; drawing has slight flicker. no double |
; buffer yet. kolibri only supports misaligned |
; 24BPP images :( images should be stored in |
; memory as 1-8BPP or 16/32BPP for fast access |
!main: |
callf set.screen,\ |
SCREEN.W, SCREEN.H, SCREEN.BPP |
callf on.create |
get.event: |
wait.event |
. event.type=r0 |
update.mouse |
if timer.speed<>-1 |
. timer.counter-- |
if timer.counter<=0 |
. timer.counter=timer.speed |
callf on.timer |
end |
end |
if event.type=EVENT.REDRAW |
; draw.begin |
callf draw.window |
callf on.draw |
; draw.end |
; retrace ; ? |
else.if event.type=EVENT.KEY |
mint 2 |
if r0<>1, r0>>8, r0&0FFh, key=r0 |
. key.event='k' |
callf on.key |
. key.event='c' |
callf on.key |
if key=KEY.ESCAPE |
callf exit |
end |
end |
else.if event.type=EVENT.BUTTON |
callf exit |
end |
go get.event |
function exit |
callf on.exit |
mint -1 |
endf |
/programs/games/codemaster/INCLUDE/TEXT.INC |
---|
0,0 → 1,1006 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ???????????????????? TEXT ?????????????????????? |
; fast portable text operations |
; text.zero t ; initialize, *t=0 |
; text.end t ; return end address (*t=0) |
; text.n t ; get # characters |
; text.copy a, b ; standard copy with 0 |
; text.copy.n... ; copy with maximum size |
; text.attach a, b ; attach b to a |
; text.attach.c... ; attach c/haracter |
; text.compare a, b ; compare lexical. <0> |
; text.equal a, b ; equal? return 1/0 |
; text.search a, b ; search for text. &/0 |
; text.find a, c ; search for c. &/0 |
; text.find.r a, c ; search for c in reverse |
; text.count.c t, c ; count # of 'c's |
; text.count.w t ; count # of words: 'a b c' |
; text.count.n t ; count # of lines |
; text.go t, n ; advance to line # |
; text.upper t ; uppercase |
; text.lower t ; lowercase |
; text.reverse t ; reverse |
; text.begins a, b ; begins with b? |
; text.ends a, b ; ends with b? |
; text.skip.0 t ; skip '0's. return & |
; text.shift.l t, n ; shift characters left |
; text.shift.la... ; shift left and assign |
; text.expand t, n ; expand; shift right at 0 |
; text.align t, n ; align; prefix with '0's |
; x2t n, t ; convert number to text |
; u2t n, t ; unsigned decimal |
; h2t n, t ; hexadecimal |
; b2t n, t ; binary |
; t2x t ; convert text to number |
; t2u t ; unsigned decimal |
; t2h t ; hexadecimal |
; t2b t ; binary |
; print t, f, ... - a fast print formatted |
; text to buffer |
macro debug { callf _say, bug.t, bug.t } |
RET equ ,0Dh,0Ah, |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; text.zero t - initialize |
macro text.zero t { . r0=t, *r0=0 } |
; text.end t - return end address: *p=0 |
function text.end, t |
alias p=r0, c=r1 |
. p=t, c=1 |
while c, c=*p++, endw, p-- |
endf |
; text.n t - get length, # characters |
function text.n, t |
alias p=r0, s=r1, c=r2 |
. p=t, s=p, c=1 |
while c, c=*p++, endw, p-s, p-- |
endf |
; text.copy a, b - standard copy with |
; 0 after. return advanced address |
function text.copy, a, b |
alias p=r0, s=r1, c=r2 |
. p=a, s=b, c=1 |
while c, c=*s++, *p++=c, endw, p-- |
endf |
; text.copy.n a, b, n - copy with maximum |
; size specified. return & |
function text.copy.n, a, b, n |
alias p=r0, s=r1, c=r2 |
. p=a, s=b |
loop n, c=*s++, *p++=c |
if c=0, break, end |
endl, p-- |
endf |
; text.attach a, b - attach b to a. return & |
function text.attach, a, b |
text.end a |
text.copy r0, b |
endf |
; text.attach.c t, c - attach c/haracter. |
; return & |
function text.attach.c, t, c |
alias p=r0, x=r1 |
text.end t |
. x=c, *p++=x, *p=0 |
endf |
; text.compare a, b - lexical comparison. |
; return <0> |
function text.compare, a, b |
alias p=r0, s=r1, c=r2, d=r3 |
. p=a, s=b, c=d |
while c=d, c=*p++, d=*s++ |
if c=0, break, end |
if d=0, break, end |
endw, p=c, p-d |
endf |
; text.equal a, b - equal? return 1/0 |
function text.equal, a, b |
text.compare a, b |
if false, return 1, end |
endf 0 |
; text.find t, c - search for character: |
; if t contains c. return &/0 |
function text.find, t, x |
alias p=r0, c=r1, k=r2 |
. p=t, k=x |
loop, c=*p |
if c=0, return 0, end |
if c=k, return p, end, p++ |
endl |
endf |
; text.count.c t, c - count # of c/haracters |
function text.count.c, t, x |
locals n |
alias p=r0, c=r1, k=r2 |
. p=t, k=x, n=0, c=1 |
while c, c=*p++ |
if c=k, n++, end |
endw |
endf n |
; text.count.w t - count # words 'a b c' |
function text.count.w, t |
try text.count.c t, ' ' |
. r0++ |
endf |
; text.count.n t - count # lines |
function text.count.n, t |
try text.count.c t, 0Dh |
. r0++ |
endf |
; text.go t, n - advance to line # |
function text.go, t, n |
loop n |
try t=text.find t, 0Dh |
. t+2 |
endl |
endf t |
; text.upper t - convert to uppercase |
function text.upper, t |
alias p=r0, c=r1 |
. p=t |
loop, c=*p |
if c=0, return, end |
if c>=97 |
if c<=122, c-32, *p=c, end |
end, p++ |
endl |
endf |
; text.lower t - convert to lowercase |
function text.lower, t |
alias p=r0, c=r1 |
. p=t |
loop, c=*p |
if c=0, return, end |
if c>=65 |
if c<=90, c+32, *p=c, end |
end, p++ |
endl |
endf |
; text.reverse t - reverse text |
function text.reverse, t |
locals p |
alias s=r0, e=r1, c=r2 |
get p=text.end t |
. e=&(s-1), s=t |
while s<e, c=*s, *s++=*e, *e--=c, endw |
endf p |
; text.begins a, b - a begins with b? |
function text.begins, a, b |
alias p=r0, q=r1, c=r2, d=r3 |
. p=a, q=b, d=c |
while c=d, c=*p++, d=*q++ |
if c=0, break, end |
if d=0, break, end |
endw |
if d<>0, return 0, end |
endf |
; text.ends a, b - a ends with b? |
function text.ends, a, b |
locals p |
get p=text.end a |
text.n b |
. p-r0 |
text.equal p, b |
endf |
; text.search t, c - search for text: |
; if a contains b. return &/0 |
function text.search, a, b |
locals n, p |
get n=text.n a |
. p=a |
loop n |
text.begins p, b |
if true, return p, end |
. p++ |
endl |
endf 0 |
; text.skip.0 a - skip 0s, return address or 0 |
function text.skip.0, a |
alias p=r0, c=r1 |
. p=a, c='0' |
while c='0', c=*p++, endw, p-- |
if c=0, return 0, end |
endf |
; shift all characters left |
; before: 'abc123' |
; after <<3: '123' |
function text.shift.l, t, n |
alias p=r0, q=r1 |
. p=t, q=p, q+n |
text.copy p, q |
endf |
; shift left and assign s to BITs |
; copied out ('abc' in example above) |
function text.shift.la, t, s, n |
alias p=r0, q=r1 |
. p=t, q=p, q+n |
text.copy.n s, t, n |
text.shift.l t, n |
endf |
; expand; shift all characters right. |
; example: 'abc123' becomes 'XXXabc123' |
; after expand 3 where X is unknown |
function text.expand, t, n |
locals x |
alias p=r0, q=r1, c=r2 |
get x=text.n t |
. p+t, p--, q=p, p+n, *p=0 |
loop x, *p--=*q--, endl |
endf |
; prefix text with '0's or ensure maximum n. |
; example: before: t='7FAB' |
; text.align t, 8 ; after: t='00007FAB' |
function text.align, t, n |
locals tn |
alias n1=r0, n2=r1,\ |
c=r1, p=r2 |
get tn=text.n t |
. n2=n |
if n1=n2, return, end ; same size |
if n1>n2, p=t, *(p+n1)=0 ; exceeds maximum |
return ; end at t+n |
end, n-n1 ; else, n2>n1 |
text.expand t, n ; expand t |
. p=t, c='0' ; write '0's |
loop n, *p++=c, endl |
endf |
; search text array ta for t using text.equal. |
; return index or -1 (<0) if not found. ta is |
; an array of text addresses (text[]) |
function text.array.equal, ta, t, n |
locals i |
alias p=r0, q=r1, x=r2 |
. i=0 |
loop n, x=i, q=ta, (u32) p=*(q+x*4) |
text.equal p, t |
if true, return i, end |
. i++ |
endl |
endf -1 |
;;;;;;;;;;;;;;;;;; CONVERSIONS ;;;;;;;;;;;;;;;;;;; |
; u2t n, t ; unsigned decimal |
; h2t n, t ; hexadecimal |
; b2t n, t ; binary |
; convert unsigned 32BIT integer to text |
function u2t, n, t |
alias i=r0, x=r1, y=r2, c=r3, p=r7 |
push c p |
. i=n, p=t |
if i=0, *p++='0', *p=0 |
. r0=p |
go .r |
end |
. x=1999999Ah |
while i, c=i, mul x, i=y, y=&(y+y*4) |
. y+y, c-y, c+'0', *p++=c |
endw, *p=0 |
text.reverse t |
.r: |
pop p c |
endf |
; convert 32BIT hexadecimal number to text |
function h2t, n, t |
alias p=r0, x=r1 |
. p=t |
if n=0, *p++='0', *p=0 |
return |
end |
while n, x=n, x&15 |
. x=*(@HEX+x), *p++=x, n>>>4 |
endw, *p=0 |
text.reverse t |
endf |
align @HEX: db '0123456789ABCDEF' |
; convert 32BIT binary number to text |
function b2t, n, t |
alias p=r0, x=r1 |
. p=t |
if n=0, *p++='0', *p=0 |
return |
end |
while n, x=n, x&1, x+'0' |
. *p++=x, n>>>1 |
endw, *p=0 |
text.reverse t |
endf |
; t2u t ; unsigned decimal |
; t2h t ; hexadecimal |
; t2b t ; binary |
; convert text to unsigned 32BIT integer |
function t2u, t |
alias p=r0, c=r1, n=r2, x=r3 |
try text.skip.0 t |
. n=0 |
loop, c=*p++ |
if c=0, return n, end |
. x=n, x<<2, n+x, n+n, n-'0', n+c |
endl |
endf |
; convert text to 32BIT hexadecimal |
function t2h, t |
alias p=r0, c=r1, n=r2 |
try text.skip.0 t |
. n=0 |
loop, c=*p++ |
if c=0, return n, end |
if c<=39h, c-30h |
else.if c>=61h, c-57h |
else, c-37h, end, n<<4, n+c |
endl |
endf |
; convert text to 32BIT binary |
function t2b, t |
alias p=r0, c=r1, n=r2 |
try text.skip.0 t |
. n=0 |
loop, c=*p++ |
if c=0, return n, end |
. n<<1, n-'0', n+c |
endl |
endf |
; convert number to text with alignment. |
; example: n2t.a 1234h, t, 8, h |
; after: t='00001234' |
macro n2t.a n, t, a, b { |
b#2t n, t |
text.align t, a |
} |
macro u2t.a n, t, a { n2t.a n, t, a, u } |
macro h2t.a n, t, a { n2t.a n, t, a, h } |
macro b2t.a n, t, a { n2t.a n, t, a, b } |
;;;;;;;;;;;;;;;;;;;;; PRINT ;;;;;;;;;;;;;;;;;;;;;; |
; print t, f, ... - a fast print formatted |
; text to buffer |
; %t %s - 'text'; "string" |
; %c - character |
; %n %u - 32BIT decimal unsigned |
; %b - 32BIT binary |
; %h - 32BIT hexadecimal |
; %r - return. insert 0Dh, 0Ah |
; %0 - 0/NULL |
; %% - % |
macro print t, f, [p] { |
common callv !print, t, f, p |
} |
; note: text.copy/reverse/etc and x2t |
; must return end (*p=0) address for this |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align integer BASE='n' |
; !print(n, $t, $f, ...) |
!print: |
alias \ ; aliases... |
s=r6, p=r7,\ ; source, destiny |
c=r0, i=r1,\ |
va.s=r2,\ ; &va[...] start |
va.n=[esp+4],\ ; # va |
va=[r2+r1*4],\ ; current va[i] |
n=[.a], z=[.z] ; temporary |
. (u32) c=*(esp+8) ; text buffer |
. (u32) i=*(esp+12) ; format |
. va.s=&(esp+16) ; &va[...] start |
push s p |
. p=c, s=i, i=0 ; index=0 |
.get: . c=*s++ ; get c/haracter |
if c=0, go .e, end ; end? *s=0 |
if c<>'%' ; not % |
.1: . *p++=c ; copy c |
go .get ; next |
end |
. c=*s++ ; %x |
if c='%', go .1 ; 2 %% = % |
end |
if c='0', *p++=0 ; '0' = 0/NULL |
go .get |
end |
if c='r' ; 'r' = return |
. *p++=\ |
0A0Dh, go .get |
end |
if c='c' ; %c |
. c=va, i++ ; get va[i++] |
. *p++=c |
go .get |
end |
if c='t' |
.t: ; %t %s - text |
. z=va, i++ ; get va[i++] |
pusha |
get z=\ |
text.copy p, z ; copy, save & |
popa |
. p=z ; advance text buffer |
go .get |
end |
if c='s', go .t |
end |
if c='n', go .n, end |
if c='u', go .n, end |
if c='h', go .n, end |
if c='b', go .n, end |
go .x ; unrecognized |
.n: |
. n=va, i++ ; get va[i] |
pusha ; copy/convert |
if c='n' ; number to text |
u2t n, p ; in selected base |
else.if c='u' |
u2t n, p |
else.if c='h' |
h2t n, p |
else.if c='b' |
b2t n, p |
end |
. z=r0 ; save end address |
popa |
. p=z ; advance text buffer |
go .get |
.x: . *p++='?' ; else, unrecognized, |
go .get ; replace with '?' |
.0: . r0=0, go .q ; error |
.e: . r0=p, *r0=0 ; success. terminate |
.q: ; return end |
pop p s |
ret ; callv adjusts esp after |
endal ; end alias |
.a dd 0 |
.z dd 0 |
;;;;;;;;;;;;;;; CHARACTER TABLES ;;;;;;;;;;;;;;;;; |
; ILT - insensitive lookup table. A-Z/a-z are |
; the same. this increases processing speed by |
; many times. example: if (tt[a]=tt[b]) instead |
; of: if ((a>='a'&a<='z')&(b>='a'&b<='z')) | |
; ((a>='A'&a<='Z')&(b>='Z'&b<='Z')) |
; TLT - type lookup table. each byte contains |
; C.X BITs to determine its type fast in one |
; comparison. example: if tt[c]&SYMBOL |
align 8 |
; byte XLT[128]= |
ILT db \ |
00h,01h,02h,03h,04h,05h,06h,07h,08h,09h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,\ |
10h,11h,12h,13h,14h,15h,16h,17h,18h,19h,1Ah,1Bh,1Ch,1Dh,1Eh,1Fh,\ |
20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2Ah,2Bh,2Ch,2Dh,2Eh,2Fh,\ |
30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh,\ |
40h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\ |
50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,5Eh,5Fh,\ |
60h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\ |
50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,7Bh,7Ch,7Dh,7Eh,7Fh |
TLT db \ |
00h,80h,80h,80h,80h,80h,80h,80h,80h,80h,40h,80h,80h,40h,80h,80h,\ |
80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,\ |
20h,10h,04h,04h,10h,04h,04h,04h,04h,04h,04h,04h,04h,04h,10h,04h,\ |
01h,01h,01h,01h,01h,01h,01h,01h,01h,01h,04h,04h,04h,04h,04h,10h,\ |
10h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\ |
02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,04h,04h,04h,04h,10h,\ |
04h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\ |
02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,04h,04h,04h,04h,80h |
; 76543210b |
C.NULL = 00000000b ; 0 |
C.NUMBER = 00000001b ; 0-9 |
C.ALPHA = 00000010b ; A-Z, a-z |
C.SYMBOL = 00000100b ; all symbols except _.?!@$ |
C.NUMERIC = 00001000b ; A-F/a-f, h,b,k,m/H,B,K,M |
C.SYMBOLIC = 00010000b ; _.?!@$ |
C.SPACE = 00100000b ; ' ', '/t' |
C.RETURN = 01000000b ; 0Dh, 0Ah |
C.IGNORE = 10000000b ; extended: 1.XXXXXXXb |
C.KEYWORD = 11111111b |
C.DIGIT = C.NUMBER or C.NUMERIC |
C.NAME = C.ALPHA or C.NUMBER or C.SYMBOLIC |
C.SYMBOLS = C.SYMBOL or C.SYMBOLIC |
C.ALPHAN = C.ALPHA or C.NUMBER |
C.VISIBLE = C.ALPHAN or C.SYMBOLS |
C.WHITE = C.SPACE or C.RETURN |
C.BLANK = C.WHITE or C.IGNORE |
C.END = C.SYMBOL or C.WHITE |
C.0 = 0 |
function is.c, c, type |
. r0=c, r0=*(TLT+r0), r0&type |
endf |
macro if.is c, t { |
is.c c, t |
if true |
} |
;;;;;;;;;;;;;;;;;;; PARSE TEXT ;;;;;;;;;;;;;;;;;;; |
; skip while type and not 0 |
; get p=text.skip.while p, C.WHITE |
function text.skip.while, t, type |
alias p=r0, q=r1, c=r2 |
. p=t, c=1 |
while c, c=*p++ |
. c=*(TLT+c), c&type |
endw, p-- |
endf |
; skip until type and while not 0. |
; kind of tricky |
; get p=text.skip.until p, C.RETURN |
function text.skip.until, t, type |
alias p=r0, q=r1, c=r2 |
. p=t, c=0 |
while c=0, c=*p++ |
if c=0, return 0, end |
. c=*(TLT+c), c&type |
endw, p-- |
endf |
; copy while type and not 0 |
; get s=text.copy.while t, s, C.NAME |
function text.copy.while, t, s, type |
alias a=r7, b=r6, c=r1, x=r2 |
. a=t, b=s, c=*b |
if c=0, return 0, end |
while c, c=*b++, *a++=c |
. x=*(TLT+c), x&type |
if x=0, break, end |
endw, a--, *a=0, b-- |
endf b |
; copy until type and while not 0 |
; get s=text.copy.until t, s, C.END |
function text.copy.until, t, s, type |
alias a=r7, b=r6, c=r1, x=r2 |
. a=t, b=s, c=*b |
if c=0, return 0, end |
while c, c=*b++, *a++=c |
. x=*(TLT+c), x&type |
if x, break, end |
endw, a--, *a=0, b-- |
endf b |
; copy until 'c'/x. if 0 or return is |
; encountered before, return 0 |
function text.copy.until.c, t, s, x |
alias a=r7, b=r6, c=r1 |
. a=t, b=s, c=*b |
if c=0, return 0, end |
while c, c=*b++, *a++=c |
if c=x, break, end |
if c=0, return 0, end |
if c=0Dh, return 0, end |
endw, a--, *a=0, b-- |
endf b |
; skip whitespace and returns |
; (if parse.skip.r?) or only spaces |
; and tabs. return advanced & |
align boolean parse.skip.r?=YES |
function text.skip.ws, t |
if parse.skip.r? |
text.skip.while t, C.WHITE |
else |
text.skip.while t, C.SPACE |
end |
endf |
; skip all whitespace, returns |
; (if parse.skip.r?) and comments. |
; return advanced & |
function text.skip.x, t |
locals q |
alias p=r0, c=r1 |
. p=t, q=p |
.get: |
. p=q, c=*p |
if c=0 |
return 0 |
end |
if.is c, C.WHITE |
try q=text.skip.ws q |
end |
. p=q, c=*p |
if c=';' |
try q=text.skip.until \ |
q, C.RETURN |
. p+2 |
go .get |
end |
endf q |
function text.get, a, b |
locals q |
alias p=r0, c=r1 |
. q=b |
try q=text.skip.x q |
. c=*p |
if c=0, return 0, end |
if.is c, C.SYMBOL |
. p=a, *p++=c, *p=0, q++ |
return q |
end |
text.copy.until a, q, C.END |
endf |
;;;;;;;;;;;;;;;; SOURCE, DESTINY ;;;;;;;;;;;;;;;;; |
align |
void source.p, destiny.p, token.p |
integer source.n, destiny.n, token.n |
macro set.source p { . source.p=p } |
macro set.destiny p { . destiny.p=p } |
macro set.token p { . token.p=p } |
function skip.while, type |
get source.p=text.skip.while \ |
source.p, type |
endf |
function skip.until, type |
get source.p=text.skip.until \ |
source.p, type |
endf |
function copy.while, type |
get source.p=text.copy.while \ |
token.p, source.p, type |
endf |
function copy.until, type |
get source.p=text.copy.until \ |
token.p, source.p, type |
endf |
function copy.until.c, c |
get source.p=text.copy.until.c \ |
token.p, source.p, c |
endf |
macro skip.space { skip.while C.SPACE } |
macro skip.white { skip.while C.WHITE } |
macro skip.line { skip.until C.RETURN } |
; skip all whitespace, returns |
; (if parse.skip.r?) and comments. |
; return advanced & |
function skip.x |
alias p=r0, c=r1 |
.get: |
. p=source.p, c=*p |
if c=0, return 0, end |
if.is c, C.WHITE |
try skip.while C.WHITE |
end |
. p=source.p, c=*p |
if c=';' |
try skip.until C.RETURN |
. source.p+2 |
go .get |
end |
. p=source.p |
endf p |
; get token |
function get.token |
alias p=r0, c=r1 |
try skip.x |
. c=*p |
if c=0, return 0, end |
if.is c, C.SYMBOL |
. p=token.p, *p++=c, *p++=0 |
. source.p++, p=source.p |
if c='''', c=*p |
if c='''', source.p++ |
return source.p |
end |
try copy.until.c '''' |
. source.p++ |
end |
. p=source.p |
return |
end |
copy.until C.END |
endf |
; MOVE TO PARSE.INC... |
;;;;;;;;;;;;;;;;;;; NAME TABLE ;;;;;;;;;;;;;;;;;;; |
; name table: |
; 'ann',0, 'kim',0, 'sue',0 |
align 4 |
void name.table, name.table.p,\ |
name.table.n, name.table.size, name.table.end |
; allocate name.table |
function create.name.table, size |
try name.table=call !allocate, size |
. name.table.p=r0, r0+size |
. name.table.end=r0, name.table.n=0 |
. name.table.size=0 |
endf 1 |
; get name address by index |
function get.name, i |
locals p |
. p=name.table |
loop i |
get p=text.end p |
. p++ |
endl |
endf p |
; search for name. return index or -1 |
function search.name, t |
locals i, p |
. p=name.table, i=name.table.n |
loop i |
get.name i |
text.equal p, r0 |
if true, return i, end |
endl |
endf -1 |
; attach 'text'. return address |
function create.name, t |
locals p, n |
. p=name.table.p |
text.n t |
. r0++, n=r0, r0+p |
if r0>=name.table.end |
return 0 |
end |
text.copy name.table.p, t |
. r0=p, r0+n, name.table.p=r0 |
. name.table.n++, r0=n |
. name.table.size+r0 |
endf p |
; remove name at index |
function remove.name, i |
locals p, q, n, size |
get p=get.name i |
get n=text.n p |
. i++ |
get q=get.name i |
. r0=name.table.p, r0+name.table.size |
. r0-p, size=r0, r0=n |
. name.table.size-r0, name.table.p-r0 |
memory.copy p, q, size |
. name.table.n-- |
endf |
; get name at index |
function copy.name, i, t |
get.name i |
text.copy t, r0 |
endf |
; name structure: 16 bytes |
virtual at 0 |
?define: |
.type dd 0 ; type: TTTT... |
.value dd 0 ; name index |
.name dd 0 ; value or index |
.i dd 0 ; anything, align 16 |
.$=$ |
END virtual |
powers DEFINE.*, ALIVE, USED,\ |
D, ABLE, NUMERIC |
; .type = |
; TTTT.SSSS XXXXXXXX XXXXXXXX XXX.NR.DUA |
; 23-16 15-8 7-0 |
; T: type: number, define, constant, label, |
; macro, register, instruction, variable |
; S: data size |
; P: parameter 1 |
; Q: parameter 2 |
; X: anything |
; N: 1=numeric, 0=symbolic |
; R: 1=redefinable, 0=not |
; D: 1=defined, 0=not |
; U: 1=used, 0=not |
; A: 1=alive, 0=dead |
; name structures. last structure is |
; defines.p+((defines.n-1)*48) |
align 4 |
void defines.p ; name structures |
void defines.end.p ; end allocation |
integer defines.n |
;;;;;;;;;;;;;;;;;;;;; ERRORS ;;;;;;;;;;;;;;;;;;;;; |
; MOVE TO ASSEMBLER.INC |
text errors.ta[]=\ |
E.NONE ='None',\ |
E.SYNTAX ='Syntax',\ |
E.LOAD ='Error loading',\ |
E.FILE ='File I/O error',\ |
E.UNEXPECT ='Unexpected',\ |
E.CPU ='Unsupported by CPU',\ |
E.ADDRESS ='Address not aligned',\ |
E.OPERANDS ='Invalid operand/s',\ |
E.AMODE ='Invalid addressing mode',\ |
E.SHIFT ='Invalid shift #',\ |
E.NUMBER ='Invalid number',\ |
E.NUMBER2 ='Number can''t be encoded',\ |
E.VALUE ='Value exceeds size',\ |
E.ALIGN ='Number must be aligned',\ |
E.POWER ='# must be power of 2',\ |
E.REGISTER ='Register expected',\ |
E.EXPECTN ='Number expected',\ |
E.EXPECTA ='Name expected',\ |
E.INAME ='Invalid name',\ |
E.NAME ='Name too long',\ |
E.RESERVE ='Reserved name',\ |
E.UNDEFINE ='Undefined',\ |
E.REDEFINE ='Redefinition',\ |
E.EXPECTT ='Text expected',\ |
E.ENDT ='Text has no end ''',\ |
E.COMMA =', expected',\ |
E.END ='end expected',\ |
E.MISMATCH ='Mismatched parenthesis' |
;;;;;;;;;;;;;;;;;;; KEYWORDS ;;;;;;;;;;;;;;;;;;;;; |
; MOVE TO ASSEMBLER.INC |
text keywords.ta[]=\ |
K.ALIGN='align', K.BYTE='byte',\ |
K.D1='d1', K.D2='d2', K.D4='d4', K.D8='d8',\ |
K.DEFINE='define', K.DOUBLE='double',\ |
K.EQUATE='equate', K.FLOAT='float',\ |
K.FORMAT='format', K.INCLUDE='include',\ |
K.INJECT='inject', K.INTEGER='integer',\ |
K.MAIN='main', K.ORG='org',\ |
K.RESTORE='restore', K.TEXT='text',\ |
K.USE='use', K.VOID='void' |
align 4 |
void keywords.ta.p=keywords.ta |
integer keywords.n=keywords.ta.$ |
function is.keyword, t |
if keywords.n=0, return -1, end |
text.array.equal \ |
keywords.ta.p, t, keywords.n |
endf |
/programs/games/codemaster/INCLUDE/WORDS.TXT |
---|
0,0 → 1,79 |
; 100+ words/phrases. maximum 3 words, |
; 1-12 letters each. example: |
; 'PREPROCESSOR' = 12 |
text words.ta[]=\ |
'ABSTRACT SYNTAX TREE',\ |
'ACCUMULATOR',\ |
'ADDRESS SIZE OVERRIDE',\ |
'ADDRESSING MODE',\ |
'ARRAY BOUNDS EXCEPTION',\ |
'ARITHMETIC LOGICAL UNIT',\ |
'ARTIFICIAL INTELLIGENCE', 'ASSEMBLER',\ |
'BARREL SHIFTER', 'BINARY TREE',\ |
'BINARY ARITHMETIC', 'BITS AND BYTES',\ |
'BITWISE OPERATION', 'BREAKPOINT',\ |
'CALLING CONVENTION',\ |
'CENTRAL PROCESSING UNIT', 'CPU CLOCK CYCLE',\ |
'COMPRESSION SCHEME', 'COMPUTER',\ |
'CONDITIONAL ASSEMBLY',\ |
'COSINE OF ANGLE', 'DATA ALIGNMENT',\ |
'DIRECT MEMORY ACCESS', 'DISASSEMBLER',\ |
'DIVIDE BY ZERO', 'DRAW TRANSPARENT BITMAP',\ |
'DYNAMIC ARRAY', 'DYNAMIC BINARY TRANSLATION',\ |
'EFFECIENT ALGORITHM', 'ENCRYPTION',\ |
'EXPRESSION PARSER', 'FILE INPUT OUTPUT',\ |
'FIXED POINT DIVISION',\ |
'FLAT ASSEMBLER', 'FLOATING POINT UNIT',\ |
'FLOPPY DISK', 'FOUR BIT MULTIPLIER',\ |
'FUNCTION PROTOTYPE',\ |
'FUNCTION EPILOGUE SEQUENCE',\ |
'GIGABYTE', 'GLOBAL VARIABLE',\ |
'EXTERNAL HARD DRIVE', 'HARDWARE INTERRUPT',\ |
'HELLO WORLD', 'HEXADECIMAL EDITOR',\ |
'HIGH LEVEL ASSEMBLER', 'HYPOTENUSE',\ |
'IF EXPRESSION', 'INFINITE LOOP',\ |
'INSTRUCTION POINTER',\ |
'INTEGRATED CIRCUIT',\ |
'KEYBOARD AND MOUSE', 'KOLIBRI OS',\ |
'LINKED LIST', 'LOCAL VARIABLES',\ |
'LOCAL DESCRIPTOR TABLE', 'LOGARITHM',\ |
'LOGIC GATE', 'LOOKUP TABLE',\ |
'MACHINE LANGUAGE', 'MACRO INSTRUCTION',\ |
'MEMORY COPY', 'MOTHERBOARD', 'MENUET OS',\ |
'MULTIPLE INHERITANCE',\ |
'NATURAL LOGARITHM', 'NO OPERATION',\ |
'NULL POINTER', 'NUMERIC CONSTANT',\ |
'OBJECT ORIENTED PROGRAMMING',\ |
'OPCODE', 'OPERATING SYSTEM',\ |
'OPTIMIZATION', 'STACK OVERFLOW',\ |
'PARAMETERS AND LOCALS', 'PIPELINE',\ |
'POINTER OPERATION', 'PORTABLE EXECUTABLE',\ |
'POSITION INDEPENDANT CODE',\ |
'POWERS OF TWO', 'PRECEDENCE',\ |
'PREPROCESSOR DIRECTIVE',\ |
'PRINT FORMATTED TEXT', 'PROCEDURE',\ |
'PROTECTED MODE', 'RANDOM ACCESS MEMORY',\ |
'READ ONLY MEMORY', 'RECURSIVE FUNCTION',\ |
'REGISTER', 'RELATIONAL OPERATOR',\ |
'RELATIVE OFFSET', 'RETURN VALUE',\ |
'REVERSE ENGINEERING',\ |
'REVERSE POLISH NOTATION',\ |
'SCALED INDEX BYTE', 'SEGMENT PREFIX',\ |
'SIGNED INTEGER OVERFLOW', 'SILICON CHIP',\ |
'SOFTWARE INTERRUPT', 'SOURCE AND DESTINY',\ |
'SPRITE ANIMATION', 'STRING LENGTH',\ |
'STRUCTURE', 'SYMBOLIC CONSTANT',\ |
'TOMASZ GRYSZTAR',\ ; :) |
'TRANSISTOR', 'TRUTH TABLE', 'TWO BIT ADDER',\ |
'UNSIGNED INTEGER', 'VARIABLE DECLARATION',\ |
'VIDEO CARD', 'VIDEO GRAPHICS ARRAY',\ |
'VIRTUAL MACHINE', 'VIRTUAL MEMORY' |
N.WORDS=words.ta.$-1 |
; pointer array |
align |
words.pa dd N.WORDS dup(0) |
/programs/games/codemaster/INCLUDE |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/games/codemaster/KOLIBRI_PUZZLE.ASM |
---|
0,0 → 1,231 |
; KOLIBRI PUZZLE CHALLENGE |
TILE.W=64 |
TILE.H=64 |
MAP.X=TILE.W |
MAP.Y=TILE.H |
MAP.W=8 |
MAP.H=8 |
PUZZLE.W=MAP.W*TILE.W |
PUZZLE.H=MAP.H*TILE.H |
WINDOW.W=PUZZLE.W+(TILE.W*2) |
WINDOW.H=PUZZLE.H+(TILE.H*2) |
include 'a.inc' |
text title(64)='Kolibri Puzzle Challenge' |
align |
integer scene |
numeric SCENE.*, TITLE, PLAY, SOLVED |
integer solved, select.x, select.y |
puzzle: db (MAP.W*MAP.H*4) dup(0) |
numeric NORMAL, ROTATE.R, INVERT.XY, ROTATE.L |
IMAGE piece.i |
piece.pixels: db (TILE.W*TILE.H*4) dup(0) |
BOX my.box, puzzle.box |
integer grid.color=WHITE |
IMAGE kolibri.i='kolibri', logo.i='logo2',\ |
wood1.i='wood1', wood2.i='wood2',\ |
close.i='x', solved.i='solved' |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
get.random equ random.x ROTATE.R, ROTATE.L |
function erase.puzzle |
memory.zero piece.pixels, (TILE.W*TILE.H*4) |
endf |
function randomize.puzzle |
locals q, n |
alias p=r0, x=r1 |
. q=puzzle, n=(MAP.W*MAP.H) |
loop n |
. x=ROTATE.L, p=q, (u32) *p=x, q+4 |
endl |
endf |
function reset.game |
randomize.puzzle |
endf |
function on.create |
erase.puzzle |
. scene=SCENE.TITLE |
set.box puzzle.box,\ |
MAP.X, MAP.Y, PUZZLE.W, PUZZLE.H |
endf |
function is.solved |
locals n |
alias p=r0, x=r1 |
. p=puzzle, n=(MAP.W*MAP.H) |
loop n, (u32) x=*p++ |
if x<>NORMAL, return 0, end |
endl |
endf 1 |
function get.piece, x, y |
. r0=y, r0*MAP.W, r0+x, r0*4, r0+puzzle |
endf |
function get.piece.rotate, x, y |
get.piece x, y |
. (u32) r0=*r0 |
endf |
function set.piece.rotate, x, y, r |
if r>ROTATE.L, r=0, end |
get.piece x, y |
. r1=r, (u32) *r0=r1 |
is.solved |
if true |
. scene=SCENE.SOLVED |
end |
endf |
function copy.piece, x, y |
locals w, h, pw |
alias p=r0, s=r1, n=r2 |
. p=piece.pixels, piece.i.p=p |
. piece.i.w=TILE.W, piece.i.h=TILE.H |
. n=PUZZLE.W, n*4, pw=n |
. n=y, n*pw, n*TILE.W |
. s=x, s*TILE.W, s*4, n+s |
. s=kolibri.i.p, s+n |
. h=TILE.H |
loop h, w=TILE.W |
loop w, (u32) *p++=*s++ |
endl |
. n=TILE.W, n*4, s-n, s+pw |
endl |
endf |
function draw.piece, px, py, x, y |
locals z |
get z=get.piece.rotate px, py |
copy.piece px, py |
if z=NORMAL |
draw.image piece.i, x, y |
else.if z=ROTATE.R |
draw.image.rr piece.i, x, y |
else.if z=INVERT.XY |
. r0=y, r0+TILE.H |
draw.image.ixy piece.i, x, r0 |
else.if z=ROTATE.L |
draw.image.rl piece.i, x, y |
end |
endf |
function draw.puzzle |
locals x, y |
. y=0 |
while y<8, x=0 |
while x<8 |
. r0=x, r0*TILE.W, r0+MAP.X |
. r1=y, r1*TILE.H, r1+MAP.Y |
draw.piece x, y, r0, r1 |
. x++ |
endw |
. y++ |
endw |
endf |
function draw.grid |
locals x, y |
. y=0 |
while y<8, x=0 |
while x<8 |
. r0=x, r0*TILE.W, r0+MAP.X |
. r1=y, r1*TILE.H, r1+MAP.Y |
draw.outline r0, r1,\ |
TILE.W, TILE.H, grid.color |
. x++ |
endw |
. y++ |
endw |
endf |
function draw.wood.frame |
draw.image wood1.i, 0, 0 |
draw.image wood1.i, 0, WINDOW.H-TILE.H |
draw.image wood2.i, 0, TILE.H |
draw.image wood2.i, WINDOW.W-TILE.W, TILE.H |
draw.image close.i, WINDOW.W-40, 8 |
endf |
function on.draw |
draw.wood.frame |
draw.puzzle |
if scene=SCENE.TITLE |
draw.box.o puzzle.box, grid.color |
end |
if scene=SCENE.PLAY |
draw.grid |
end |
if scene=SCENE.SOLVED |
draw.image.v solved.i, 132, 13, WHITE |
else |
draw.image.v logo.i, 180, 13, WHITE |
end |
endf |
function on.key |
; ... |
endf |
function get.select.xy |
. r0=mouse.x, r0-MAP.X, r0-WINDOW.X |
. r1=TILE.W, r0/r1, select.x=r0 |
. r0=mouse.y, r0-MAP.Y, r0-WINDOW.Y |
. r1=TILE.H, r0/r1, select.y=r0 |
endf |
function on.mouse |
locals r |
if mouse.event='c' |
. r0=&close.i.x |
if.select r0 |
exit |
end |
if scene=SCENE.TITLE |
reset.game |
. scene=SCENE.PLAY |
go .draw |
end |
if scene=SCENE.PLAY |
if.select puzzle.box |
get.select.xy |
get r=get.piece.rotate \ |
select.x, select.y |
. r++ |
set.piece.rotate \ |
select.x, select.y, r |
go .draw |
end |
end |
if scene=SCENE.SOLVED |
reset.game |
. scene=SCENE.TITLE |
go .draw |
end |
.draw: |
render |
end |
endf |
function on.timer |
; ... |
endf |
function on.exit |
; ... |
endf |
/programs/games/codemaster/MEDIA/0.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/1.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/1000.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/A.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/B.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/C.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/D.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/E.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/F.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/G.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/H.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/I.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/J.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/K.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/L.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/M.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/N.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/O.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/P.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/Q.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/R.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/S.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/T.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/U.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/V.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/W.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/X.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/Y.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A/Z.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/A |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/BITS.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/FONT.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/SMILE.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/X.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/arm1.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/arm2.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/board.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/body.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/head.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/kolibri.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/leg1.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/leg2.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/logo.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/logo2.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/money.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/solved.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/stand1.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/stand2.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/wood1.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA/wood2.bmp |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/programs/games/codemaster/MEDIA |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |
/programs/games/codemaster/ReadMe.txt |
---|
0,0 → 1,39 |
3 GAMES FOR KOLIBRI (AND WINDOWS) |
Binary Master: Fun game for programmers. |
Practice binary arithmetic. |
Hang Programmer: Teaches English words/phrases |
related to programming |
Puzzle Challenge: Custom game for Kolibri. |
Tests your visual attention to fine details. |
If you solve the puzzle, lines will disappear |
and there will be a message. Look close into |
the clouds and direction of lights. |
Written in FASM(1) macros, Abakis advanced language |
+ library, 7,000+ lines, custom graphics and fonts. |
Spent the most time on this library. |
* Created by codemaster (codemazt3r@gmail.com) |
* Educational games made specifically for programmers. |
* Very clear professional style, good examples |
for the community. |
* First portable games written in FASM. Assembles |
on/for both Kolibri and Windows with the same |
source just by changing the first 1-2 lines |
in A.INC. Allows programmers to create games |
_for_Kolibri_ on Windows |
* 24-27 years of programming experience, |
recreationally in my freetime. Made 1,000s of |
programs, given 100s of examples away for free |
while poor. Never been paid. |
Thanks. Happy new years! |
=========================================================== |
(1) FASM is the abbreviation for Flat ASseMbler, open-source |
assembly language being developed by Tomasz Grysztar. |
FASM is available for Windows, DOS, Linux and KolibriOS. |
You can download FASM from: http://www.flatassembler.net/ |
/programs/games/codemaster |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |