Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 5304 → Rev 5305

/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/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/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/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/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/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/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/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/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/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
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/games/codemaster
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property