MV - CPCEMU Disk-File Disk-Info (Track-Info  NABCDEFGHITrack-Info  NABCDEFGHITrack-Info  NABCDEFGHIHISOFT-CBIN HISOFT-CBINCSTDIO LIBI !"#$BASIC2 LIB,%&'()*BASIC1 LIBw+,-./0123456789EXTCMD H :;STDIO H <=>REVERSI C o?@ABCDEFGHIJKLREAD ME MFIRM4 LIBDNOPQRSTUVFIRM3 LIBJWXYZ[\]^_`FIRM5 LIBeabcdefghijklmFIRM2 LIBenopqrstuvwxyzFIRM6 LIB{|}FIRM1 LIBI~HISOFT-CBINa@aaak ÿ4vÌëëâcä ïE0?:!99*N90!!ystack overflow^V9DM}o|g}o|g}o|g)<,+|/g}/o|!#|zI|M!)8 08||zIPBK>)8= ){zrW{_,= 4PɯRgo͂7#?+͂#7͑+?+?͙#7͂#Ͱ#7!{;͈#;;A?[#;;# ; o;o!#+w#xR8  ~#fo n& s#r ss#r^#V r+s^#V r+sKN#F#x( ~#~# `iɷR!͈0)]T))_YPP{0:8+w} |(z+6-o*L*w#"!!( !"9^#V++>2~(% % ~*>! "oog"q-> 2n0 2o͈0ͩ"s. 2rͩ"p=!}pd(u(( o("x(s(c( - s# s :r( *pͰ0*s+R#!DM*n{(~#~*n++x|~ "9^#VS+++a0 l a0 V+^ *~#"*I}*+w"o&*j!_y!jS|(!j"!"|!"9^#V++>2~2{!"n(/ ~({%('o~( [nz {[n9!*2p ͈ܩ"q=h(/d(+ o(%x( c(es(o~0 ~x(X{!PY`hKqx(' ~08 8 8 0 OB {:p(Ms>h(6#r2~o:p(8}$Kq~ {o:p(} x .*n#"n++!I}*~#"o&$PE|(͂} (<(>P(>͂>͂!6"!6]T!N#F#^#V#x RdR PR! 6̈́{Å}Z}>$ > Z> Ź̈́ > o&!}o& !8 , !?7,?}շO(8 8}͕͒*$}Z}+{!_W(^w{ (!̀o&}{ z}!w}!L ( ˆz0xˎV ˆ͏!w!w!Lw*"> z> zE[Lr(w()C %[wK S C [͌!{2L> o"!LʹDM͘â!>`i˼P n& s#r ss#r^#V r+s^#V r+s&Á#͐ ͐͐ ͉͐"`is͐ ͐͐ )͐"`in&#&Á#!9!9DM! n&|ͯڵ#! n&1 K KJ{Vb b b b b b b b b b b b  ^#V#* ~#fo^#* ~#fo^#V#* n^#* n^#V# ~#fo^#& ~#fo!+!#!+!#!+!+Track-Info  NABCDEFGHI}|z{|}| z7| |7zZ Z ) |/g}/o#|͉ k |/g}/o#ɯ2 Z Z k : |/g}/o#|/g}/o#: <2 q DM!xxGyO҃ )v |͔ `i| )Ö x ڷ z/W{/_ѯzW{_=yOxGæ 2 Z Z ͉ M |}ȯ|g}o ) |/g}/o#z/W{/_!9~#fo! ! ! ! ! !  !9~#A " !!2 2z * !#<!Eͷ~P !ͷ’P͌Q!ͷªP}QxQ!ͷ͓G@>2!V!"L>2"VA{D A| (| ͈ p m |! !CAm *L|j >B"L>2"V!MB͌!MB!MB>2"V$ *LA*L&Bm ! (C*TS++"QA#*TS "T*L"a͜)t(#~#fo"w$ *!V} *L *L "a>B2*L "N ! ͩA!UA| !! ͩA!PA Type y to run: *L2 "N!9DM͐ |~ *L͐ 2͐  v ͐ 2*L ~ !<C*L͐ "L͐ #`is#r͐ | ͐ )L~#fo͐ s#r`i^#Vr+sÙ !9>6! ͜A HISOFT-C Compiler V1.2 Copyright 1984 HISOFT *L[L[LRDM@!L!VF!P*L >*6wx͎˽u`Ou$}±x2Y͇Rʱ"Zͷx*Y*Z} o͇0 Rʳͷ"Z-%J!tV!nV!nVH 0 ́̈́E!00 ~# ( (*\q#p" ~#(" o }~# ( ٯ!89"\! -"^#)9DM:^*\#=(4#^#V͈0 ͩs#r" ++}q#p{z:^W+( ~#~++!Լ0 :^=!91ͧ7ȼ!@˼{Vp x @*C*DU###~#fon&|ڰ|ʰ|ʰ!AC*DU#~#fo"/V*DU#~#fo*DU###~#fo!9DM͐ n`is#6͐ #~#fo! s#r͐ |#͐ ͐ ͐ ~u͐ |H͐ ͐ ͐ u͐ |m͐ ͐ ͐ Cu!?C!9!9DM!{)`is#r͐ ͐ x22͐ |ʹ!}!9!9DM͐ ###~#fo#~#fo! s#r͐ |͐ ͐ ͉ !! s#r!{)! s#r|¢͐ ###~#fon}¢>B! s#r*K! s#r͐ n}!! ^#Vr+s! ^#Vr+sn&2J͐ *K #`is#r͐ &B`iw#w͐ ͐ ###~#fo! ~#fo͐ s#r`i^#Vr+s͐ ͐   |¨͐ #|)*DU#͐ #͐ ͐ k s#rA(s#r"/V͐ |:!}! 9!9DM͐ ͐ ! s#r!{)! s#rx2`is#r͐ ͯ ڋ!Î!! s#r͐ ͐ ͐ 2! ~#fo͐ s#r͐ ͐  !@C͐ ͐   |n͐ |!}!9|"!,|ͣ !9DM͐ ͐ */V *L ! s#r͐ !PC͐ *L*L͐  [*L*L͐  ! s#r͐ ͐ ) s͐ ++|! ^#Vr+s͐ ͉ s!9!"%V")V*TS####"'V*'V#"#V!ZC!ZC!9DM*%V*#V*/V *L "%V*/V*L"#V*L*%Vͩ ]!`*%V! s#r*L`is#r͐ !PC*L͐ *L͐ ~A͐ *L *L*L[*L*L*L~A*L"+V͐ "-V!ZC*+V|O*#V+"#V*+V+"+V*Ln! s#6͐ |*%V#"%V*%V%*%V+"%V#|=!͘%!"%V͐ ͘*-V*L  ! s#r*L*L*-V͐ ~A*-V !PC!9!9DM*-V+"-V*L͐ s*)V#")V!9DM͐  ͐͘ ͘!9DM*)V`is#r*'V͐ #;͐ ;*#V"'V!")V!"%V!9!!PC*L####*L*L++++~A!"-V!9DM! ^#Vr+szʆ! ^#Vr+s6c*K"K*tLR 2DI|<(z(:{L=}K}˽&fo"Kz( !Z(O!wL(5!L(^W5~#fo"tL!˯2L&o:L :K2L!KK go"K͍8 T (#(Y͐Kx2Ka:K*K͈KKy (Xx2K (LD.I:"y'#( .(\(5:K ʈy͈:KD.F:͈:K ͈2KÈ!X:Kw͈:KL(D #> #wD%"K͍%>}2K!DT:KO:KD y0Lya0 WO ͈}F(Q:K0 ͈:Ka0 x ͈ "K "K:K.(:Ka0 e(:Ka0 lÈpC͈&:Ko (^\͈&:K. (n. t.b. r. fo:KD}0o:K0O}o͈͈͔"K͈:K'pC͈!9:"VB>B"K:K"( ͔][B_[BBÈ͈ !x:K# ,:K &> 2K͈:K* :K/ ^͈>M2K#:K/*==!=++--&&||<=<<>=>>->TL ͽ%!>2%(A = pCdefine include diagnostlist direct error translato&)Z!yL!{L pC:!V!L :K- 5+ 4û!9!L4ng)L[tLs#r !D!"tL!9!ZF} pCr &B*L[L+wTL(pC:K( :K (Track-Info  NABCDEFGHIpC[Lͤ%͏T (͏L( D('(" }͏|͏:L=*Lw:K :K_ (͈?!wL~((( ?( w#͈6ûL͍%| gG[LO !L[L R0 SLpC*LLR~#2KL( D('(" ^#V#SK"L7:K ͈<:!KK^#(pC#!spCmissing ' '^#;&l!^#<;d!^C!L"L! "Kgo"L"yL"wL"tL2K2K2K2L2L#"}L"{L!*Kͽ%2%(Bͽ (f2inline W@ sz M   ; {L#(<)x2| MBTB<,(^#V#*eT*cT*bTCeTScT{>(<2bT"bT"cT"eTBK>B͌ !cTB(B!9!#l2)!eTB>>BB!eTͶ!cTB!eTB>#(!+l2)͌#(SBKJ(f2>BJ(B"cTf2(!9B)!bT!BB͌!cTB!eTB>:bT :gT !eTB#;pC :bTO(/G!cTBBpC !9Ͷ< !9BB͌BB*eT:gT*jT*hTgo"eT"jT2gT#(f21ͥB͉>BͬB)͌!eTB!9B*hTShTRMDBͬB*jT}(!jTB!eTB"jT2gT"eT:gT(pC *hT[:UR] pC >B*hTs#r#x2s#r#"hT::gT(pC *jT}(pC>B"jT#:L(pC*K͉(#( BÀpC*K͉(( 6 #B;(f21+}͌ bT!!!4U":UlTZ!͋!J(%X$( (!><=8J( <,(pC0a$$!KU:ZT  ~2<!_U G#N^kb))lM"@UG y(( ! y !M"@U "}! c5"@U!qM"@U!L*K|(~!(#L "*K|(}(c5"a{ pC3":ZT pC4!lM"a9DM!a> %L *ZT*a! *K͡&{: 2X$*a[BU͈0pC5{(*VSͯ0!"VS<,(} *VS*a#s#r"VS2 *BU~( ( (pC- *wL}(*>U͍%}( ~ #~# >*ZT[BU>  -*U͡&"DU<*(<( ~#)L *K">UpC6#y( > &<((<[(P<)(9(:(6(2>L +!!qM!*K͡&<,()> &pC7pC8 > &]x2] gox2&]<[(*@U"BU#*DUc5(pC9<! #[DU> "8U>2ZT$<{ ͫ)>2ZT2"V%*XT͵B!!B͌<} +2"V<2ZT)<{ { }  y )<>2X$<,(!(!$%! <%~*L[L (' R8`i>B*LR2%( ~ [L^#VÑ% [Ls#ré%[L2PCQ^#V"SP2%("*`OR(  *bOR8S`O!Ps#rpC3*U#s#r"U>3*UVz+"U*BU^ ( {( ( pCz { pC*UV+^+"U*BU#~#foDM>!BU%}l#͍%͎&*NSͶ*LSͷ"P}2R"U}2W*P&ħ'͆&0dc5*UR(pCN:R(($(( (,pCy((6#Bɹyy 6ɹ #^#V*VSR !"S:R*U( ( (>~ :R >B"S͉'[LS*PSR8pC!VSLS*Pͤ%͓'*U#^#VE(*VS"S*U#~#fo"VS͝%:W t}(:R  c5*URpC:R!(( ͓'*U#^#V*XTR"XT"S͉'[RT*VTR pC!V*P͵%"RT[U}( :Rw###s#rpC:!V( BB[L*LR8 "L*TSR"S"TSpC|(T]͝%}bkÍ%͒(|~DM͝%}( ~ !*VT[RTR pC`i͵%6 "RT͜)|(2P#~#)KL*`M ͆&0~ (  #~#()B 8:Pgo> Â!*)͏A*L>2PÜA ERROR - 27 - undefined symbol V)c)r)!M"`O![O"bO*`M[LR>B!dO"PS*RS"LS!GS"NS!"ZT.!M.͜)͡&!)D%main [RT*TTR8 #q#p###! "6U!"4U"XT!"XT!XS"VT!RT"RT!MT"TT*LKL DMů^w#Vw !6*͏A>͜ApCB 8undefined label: !9DM͐ !!͂*!9DM͐ !!*!9DM͐ ~#fo*M ++`is#r͐ |*͐ MB͐ MB*͐ ~#fo͐ ͐B!9!9DM͐ MB*M`is#r͐ ~#foTB͐ ~#foC͐ ͐ s#r!9!9DM*M*M `is#r͐ C͐ ~#fo! s#r͐ *Ms#r͐ ͐ ! s#r͐ C͐ |O+!9!9DM͐ !͐B!9DM͐ n}+͐ #!!*+͐ #~#fo͚+*4U|,!4UH*8,*M"4U*8U|,!!͐B8,*6U!͐B!!͐B!9DM͐ !*͐B͐ ++|c,!&TB!9DM![TB͐ TB͐ ++|‘,!TB!9DM͐ |ڵ,͐ |,͐ | -͐ ++| -!nTB͐ MB͐ ++|,!fTB͐ #MB-!&TB5-͐ !!͐B͐ ++|--!G͚+5-!P͚+!9DM͐ ++|U-!K͚+e-!nMB!&TB!9DM!^MB͐ ++|ʕ-!#MB!VMBÝ-!TB!9DMͣ21*U#~#fo`is#r*Un&Track-Info  NABCDEFGHI|g}o|-͐ *iU&3..*Un&|g}o| .͐ *iU&ͧ..͐ *iU&o.*iU}*.!&TB!9!9DM͐ ++|W.͐ !"͐Bm.!}MB͐ !2͐B!9DM͐ ++|ʍ.!j͚+å.!MB!}MB!MB!9DM͐ |.͐ |.͐ |/͐ ++|/!uTB͐ MB͐ ++|/!tTB͐ #MB>/͐ !͐B͐ ++|6/!X͚+>/!b͚+!9DM͐ n`is`in&|g}o|}/1͐ #~#fo!!͐B/`in&|g}o|/1͐ #~#fo!!͐B!TB!MB! MB/`in&|g}o|/!"C>2lU!9!9DM͐ ###~#fon`is͐ #~#fo! s#r͐ n! s! n&|g}o|L01͐ !!!*0! n&|g}o|u01͐ !!͐B0! n&|g}o|ʠ01͐ `in&:,0! n&|g}o|01͐ `in&͓,0! n&|g}o|0͐ `in&7-0>2lU!9*lU}1!MB>2lU*U/*U/!9DMͣ2*Un&|g}o`is#r*U#~#fo"jU3|w1$1*jU!!*13|ʒ1$1*jU!͐B]2'3|ʯ1$1*jU*hU&e,]2,3|2͐ |1$1!MB>2lU1*jU*hU&͓,>2lU!MB͐ |2>2lU$1]2"3|92*jU*hU&g-͐ |.2!MB32>2lU$1]2!MB͐ |U2!MBZ2>2lU$1!9͑2_6f2128_613( *U#^#V2pC'!U"U!qU"Uw2lU*U"Uc52hU"Uc52iU*U@8 U"Uã2pC*U"Uуууу2Ϳ2*UwSjU#s#r#s#r2hUC>33>33>33>33>*U!#*UV(6B6>2hU###%/1:pUMo&)^#VB~3*U6:pU8 880qM*U###s#r26(((:iU((:hU( :oU({MM}3[U!s8 SUCpC00  >C*UN:hU3X*UN:iU3K[pU2mU2nUWx 2oUx (y ({8 0 8_:oU(Y{_SxW($ I<2nUC[U*U>5(5[U*U>5()#{(J(F((((((pC { @(:oU( {  {2pUX( I(r5 +H('Y(#` a ͞B*UT]   X(*Uc5*Uc5R}´4<2mUc5c5 F( #~# #s#rR###~#fo~͠5*Uc5c5e5!qM>2:pU >>*Uw>2pU32nU:hU3:pU$(&('()( *( %(#(XP(H2nUpC!*U###T]f5c5s#r=3(͋!} pC&)*U^ pC"*K|(}(9~ 4#^#Ve5~( #N#F r+s ͵B͞B###s#r5CpC#*U72`!U(#> 80 <= 2`>  _z{( <:> >o&U>( )<U>*3>-+ 5*U#[@Us#r"U>+3[KD!qM('!vM("!M((((*L(2pC$>2685*@U#^#V!qM>2_6)|(}(#!!M!*K͡&((pC%͎&8 ~(> > #^#V#F#fh25:hU ((=3~ *U6#s#r<[(<N(:<.(?<(d9ɯ3_6]>!3>3*U~2pU("<+"U>!2pU3"<6!8*pU&M)^#V*U#^#V*Ue5~3:mU(*U###^6q#V6M#^#V4*U6#s#r!9DM͐ |8!*8!*`is#r!}MB!MB͐ |89͐ ͐ !! !19!9~#fo[9͐ ͐ !!(!W9!9~#fo!9!9DM*hU}}9!(C`i6#6'3|˜9|ʛ91|9_61*U"U`i~#fo##s#r1!,)|§9!)'3|:͐ n} :͐ !͐B!MB͐ Ͳ+×:͐ ++|B:͐ ++!!͐B!9MB!!7-͐ n} c:͐ !͐B!MB>B!͐B!MB!MB͐ ++|ʗ:!MBx3*U###*U###~#fo###~#fos#r>2lU!9!9DM͐ >:>;>:>;>:>;>;>\;> ;>ʵ;<*U#"U*U#*Uss1*U!͐ |͝ 8>2lU*U#"U*U"U<*Un}n;!)C1>2lU*U++`is#r͐ ~#fo! s#r͐ w#w͐ e*! ,+*U+"U<"3|;!*C͐ | <'3|;,3|;!MBͿ2*U*U!~A͐ 3! 6,#6<͐ 3!9ͣ2*pU&|:<4=T>g>g>>>+>$&?#&?%&?!?".@&4@'D@)T@*d@t@`3|@13|ʝ=*U#~#fo+|=*U"U|@`3|@/1!MB~3|@/1!MB!RTB~3*mU}5>*U###qMs#r*U###~#fo###~#fo#~#fo`is#rz5>!qM͐ !!!!2*Us{2pUà<|@*U*U+ns*U+6*U#"U|@͟-*U"Ux3|@1>B`is#r`i!!8*pU}ž>!!!͐B*U++"U*U,+*pU}>!!!͐Bx3*U###qMs#r|@1*U++"U*U,+~3|@!+C|@*U++"U! s#r*U###͐ ~#fos#r5|@13|ʝ?*U#~#fo`is#r*pU}$R?#d?%t?Ç?͐ |͝ `is#rÇ?͐ `is#rÇ?͐ }/o|/g`is#rÇ?*U6*U#͐ s#rö?1*pU&)M~#fo͚+x3*hU}?*Track-Info  NABCDEFGHIpU}$?*U###qMs#r|@*hU&{&|?!,C13|@*U6 @1*U6*U###*U###~#fo###~#fos#r5ͣ2|@=3|@!!ͅ@|@!!ͅ@|@!!ͅ@|@!!ͅ@|@!-C!9!9DM*U@/*hU}@͐ |ʯ@!~MB͐ |@!5MB@!4MB͐ |@!oMB@!nMB!&TBgA*hU&{&| A*U###~#fo###~#fo#~#fo`is#r'A`i6#6͐ |=A͐ `is#r͐ !͐B͐ |_A!}͚+gA!r͚+x3!9!.C.~(͂#G~͂#ÏAo!L*VA*TSdA"TS[LR"LCO BRJ)) Ñ2!^C*L"M:!V(! "M*MR"M*MR"M*M*M[MR[BÉB*L[L*MR#>B*MsC#"M*M#"M[BZ[B[BÉB^#[B^#[B^#V#ÉB_[BÉB^[B,+e*H*@/͚+DMo&)L^#V r+s N#F# N#F+B'CZ.CɷR0#T] *LBo&l94 .}B})L^#VB~ #^#V!C(_*L|(*L{(# !C!yAUEyDC ERROR %d %s }2CpC:yL~#o&)C^#VCCCCCC*bV[L| bk"bV!DR[LRDMJ*L"dV"fV!_V[dV@DSdV*bVR+!_V^(˞SfV &otDy%5u G"hVClVsjVD{jV=J"g"iD!D:m!ZJo }#^#V#yH=JC> Â͂E!JÏA>>͂G2m | sÏD͈0 eElI8K`VIE( eE"[V"gIE( eE"]V"iIE!1VSEIE !FVTEDÏD 7ȹ7?IE(w#IE6ͩ|(J > 2gI> 2iI `iIIIRJDMJ:1V 2`VJ  IN#F*i|(B8'`iNcD#~Nİ +I !1VF"b|rwFFD*bVKLB W_+(> B (+ #^#V Jw J! sJr*bI} (Ѽ > (Jw#+J"bV*bOIK]VIIѷR!DFFDbkB0@D*b^( LL$nEF*LI[gx(s#r+KiJGI:`V͂*[VcD*]VcDD!1V3G!FV3G*LcD*bVcDD͏A{jVKlV*hVIjG! HͰH[`RBHI7N#F#J*]VBCgC`!1V~7~ (ξ#(K`fIJ*kT]~ nE`iG"gDMI(-!6 2*i|D*bV[LR!D*fV^#VSgJI##JͰH! H|!JOìDXy F(ͰGq!ͲIQͰGyaḦ́HͰG͂#"k*kR+>͂N ͂y#NHͰG#~#aH> ͂>NH BH !_V~w*k~ (> ͂#!"kV*gcD͏HV[`͢G0!1V͹I_!FV͹IOBH!ͲIQ*I+*` ͝HJH [`(͏HD͢GQGV[`!? !!!͎}?opQJÏDQJV*gDMͲI_I( ##ͲID_8BKxJJxJs#r#> ͺI<ɯy/K[V*LI(^#V+BI##> # [bVRJ*i}7Kgx~ KbVJSbV`iRDMR8 ͱR!_Vw2dgo͏HDÎBDGC8GDDEGFEGGFIGLENFPFSEVGWEBHNHoHsH ]IHHHHWIHH,I8I=IBIGIHPardon? #`i>B"L͐"L͐"L͐"L͐"L͐"L͐"L͐"L͐"L͐"L͐"L͐"L͐"L͐"L͐"L`i~#fo͐s#r! 6#6͐"L͐"L`i~# E E !"#$%&'()*+,-./DDDDDDDDDD:;<=>?@LLLLLLLLLLLLLLLLLLLLLLLLLL[\]^L`LLLLLLLLLLLLLLLLLLLLLLLLLL{|}~VVVVVVVYYaL 4xP} !"&'()*+,-vMqMqMMMTrack-Info  NABCDEFGHI M M M M M M.M M MMMMMMMMjMaM^M[MmMUMOMLMIMFMRGSdOR $$=? STXW<>RP|^&OQ+-*/%*&-!~VU    , auto break case cast char continuedefault double do else entry extern float for goto if int long registerreturn short sizeof static struct switch typedef union unsignedwhile fopen GSgetc BSputc =Sfclose 8Srawin 3Srawout .Skeyhit )Sgetchar $Sputchar Sungetc SsetbufouSisdigit Sisalpha Sisupper Sislower Sisspace Rtolower Rtoupper Rswap Rblt Rsprintf Rfprintf Rprintf Rsscanf Rfscanf Rscanf RRESTRICTION : floats not implementedbad character constantnot a preprocessor commandmacro buffer fullcan only define identifiers as macrosRESTRICTION: macros may not have parameterscannot open fileRESTRICTION: cannot nest includesmissing 'while'not in loop or switchnot in loopnot in switchLIMIT : too many case statementsmultiple default statementsgoto needs a labelmultiple use of identifierdirect execution not possible when translatingLIMIT : name table fullLIMIT : too many typesduplicate declaration - type mismatchduplicate declaration - storage class mismatchLIMIT : global symbol table fullLIMIT : too much global dataduplicate declarationLIMIT : local symbol table fullthis variable was not in parameter listundefined variable(s)bad function return typeno arrays of functionsLIMIT : expression too complicated - too many argumentsLIMIT : expression too complicated - too many operatorsbad type combinationbad operand typeneed an lvaluenot a defined member of a structureexpecting a primary hereundefined variableneed a type nameneed a constant expressioncan only call functions : does not follow a ? properlyDestination of an assignment must be an lvalueneed a : to follow a ? - check brackettingneed a pointerillegal parameter typeRESTRICTION: Floating Point not implementedcannot use this operator with float argumentsbad declarationstorage class not valid in this contextCOMPILER FAULTduplicate declaration of structure taguse a predeclared structure for parametersstructure cannot contain itselfbad declaratormissing ')' in function declarationbad formal parameter listtype should be functionCOMPILER FAULTCOMPILER FAULTLIMIT: no more memoryRESTRICTION: use assignment or blt() to initialise automaticsCannot initialise this (disallowed storage class)Cannot initialise this (disallowed type)too much initialisation databad initializer (needs a '{')!a`i˼ ""+"V!@ structure taguse a predeclared structure for parametersstructure cannot contain itselfbad declaratormissing ')' in functionTrack-Info  NABCDEFGHI /*****************************/ /* Hisoft C */ /* Standard Function Library */ /* version 1.2 */ /* Copyright (C) 1984 Hisoft */ /* Last changed 15 Apr 1985 */ /*****************************/ #list- /* Some arithmetic functions */ /* min and max are in "stdio.h" because they are variadic */ int abs(n) { return n<0 ? -n : n ; } int sign(n) { return n ? ( n<0 ? -1 : 1 ) : 0 ; } /* An illustration of how to grub around in the store */ typedef char * __char_ptr; int peek(address) { return * cast(__char_ptr) address; } void poke(address, value) { * cast(__char_ptr) address = value; } /* Input and Output */ int out(data, port) { reg_bc = port; reg_hl = data; inline( 0x4BED, ®_bc, /* ld bc,(reg_bc) */ 0x2A, ®_hl, /* ld hl,(reg_hl) */ 0x69ED); /* out (c),l */ } int inp(port) { inline( 0xE1DD, /* pop ix */ 0xE1, /* pop hl */ 0xC1, /* pop bc */ 0xE5, /* push hl */ 0x68ED, /* in l,(c) */ 0x26, 0, /* ld h,0 */ 0xC9); /* ret */ } /* Format conversion routine - ASCII to binary integer */ int atoi(s) char *s; { static int c, value, sign; while (isspace(*s)) ++s; value = 0; sign = 1; if (*s == '-') { ++s; sign = -1; } else if (*s == '+') ++s; while (isdigit(c = *s++)) value = 10 * value + c - '0'; return sign * value; } /* Sorting function - a Shell sort */ void qsort(list, num_items, size, cmp_func) char *list; int num_items, size; int (*cmp_func)(); { static unsigned gap, byte_gap, i; static char *p; for (gap = num_items >> 1; gap > 0; gap >>= 1) { byte_gap = gap * size; for (i = gap; i < num_items; ++i) for (p = list + i * size - byte_gap; p >= list; p -= byte_gap) { if ((*cmp_func)(p, p + byte_gap) <= 0) break; swap(p, p + byte_gap, size); } } } /* String Handling Functions */ char *strcat(base, add) char *base, *add; { static char *dest; dest = base; while (*dest) ++dest; while (*dest++ = *add++); return base; } char *strncat(s1, s2, n) char *s1, *s2; { static char *s; s = s1; while (*s) ++s; while (n-- && *s2) *s++ = *s2++; *s = NULL; return s1; } int strcmp(s, t) char *s, *t; { while (*s == *t) { if (! *s) return 0; ++s; ++t; } return *s - *t; } int strncmp(s1, s2, n) char *s1, *s2; { if (!n) return 0; while (*s1 == *s2) { if ( ! *s1) return 0; if ( ! --n) break; ++s1; ++s2; } return *s1 - *s2; } char *strcpy(dest, source) char *dest, *source; { static char *result; result = dest; while (*result++ = *source++) ; return dest; } char *strncpy(s1, s2, n) char *s1, *s2; { static char *s, c; s = s1; c = *s2; while (n) { *s++ = ( c ? ( c = *s2++ ) : 0 ) ; --n; } return s1; } unsigned strlen(s) char *s; { static char *p; p = s; do ; while (*p++); return p-s-1; } char *strpbrk(s1, s2) char *s1, *s2; { while (*s1) { if (strchr(s2, *s1)) return s1; ++s1; } return NULL; } int strspn(s1, s2) char *s1, *s2; { char *s; s = s1; while (*s) { if ( ! strchr(s2, *s)) break; ++s; } return s - s1; } int strcspn(s1, s2) char *s1, *s2; { char *s; s = s1; while (*s) { if (strchr(s2, *s)) break; ++s; } return s - s1; } char *strchr(s, c) char *s, c; { do { if (*s == c) return s; if ( ! *s) return NULL; ++s; } while (TRUE); } char *strrchr(s, c) char *s, c; { static char *t; t = s; s = NULL; do if (*t == c) s = t; while (*s++); return s; } /* Character Test and Manipulate Functions */ /* NB - the common ones are built-in for efficiency */ int ispunct(c) char c; { return isprint(c) & ! isalnum(c); } int isalnum(c) char c; { return isalpha(c) | isdigit(c) ; } int isxdigit(c) char c; { c = toupper(c); return isdigit(c) | (c >= 'A' & c <= 'F'); } int isascii(c) char c; { return c < 0x80 ; } int iscntrl(c) char c; { return c < ' ' | c =Track-Info  N A B C D E F G H I= '\177' ; } int isprint(c) char c; { return c >= ' ' & c < '\177' ; } int isgraph(c) char c; { return c > ' ' & c < '\177' ; } int toascii(c) char c; { return c & 0x7F; } /****** FILE SYSTEM ******/ char *fgets(s, n, fp) char *s; int n; FILE *fp; { static int c; static char *cs; cs = s; while (--n > 0 && (c = getc(fp)) != EOF) if ((*cs++ = c) == '\n') break; *cs = '\0'; return ((c == EOF && cs == s) ? NULL : s); } char *gets(s) char *s; { static int c; static char *cs; cs = s; while ((c = getchar()) !=EOF && c!='\n') *cs++ = c; *cs = 0; return ((c==-1 && cs==s) ? NULL : s ); } void fputs(s, fp) char *s; FILE *fp; { static int c; while (c = *s++) putc(c, fp); } void puts(s) char *s; { static int c; while(c = *s++)putchar(c); putchar('\n'); } /* Storage Allocation and Freeing (Heap Management) */ char *calloc(n, size) unsigned n, size; { static HEADER *p, *q; static unsigned nbytes; char *sbrk(); nbytes = (n * size + (sizeof(HEADER) - 1)) / sizeof(HEADER) + 1; if ((q = _allocp) == NULL) /* no free list */ { _base._ptr = _allocp = q = &_base; _base._size = 0; } p = q->_ptr; while (TRUE) { if (p->_size >= nbytes) /* big enough */ { if (p->_size == nbytes) q->_ptr = p->_ptr; /* just right size */ else { /* split block and allocate tail */ p->_size -= nbytes; p += p->_size; p->_size = nbytes; } _allocp = q; return cast(__char_ptr) (p+1); } if (p == _allocp) /* wrapped around free list */ { if ((p = cast(HEADER_PTR) sbrk(nbytes * sizeof(HEADER))) == ERROR) return NULL; p->_size = nbytes; free(p+1); p = _allocp; } q = p; p = p->_ptr; } /* end while TRUE */ } void free(block) char *block; { static HEADER *p, *q; p = cast(HEADER_PTR) block - 1; for (q = _allocp; !(p > q && p < q->_ptr); q = q->_ptr) if (q >= q->_ptr && (p > q || p < q->_ptr)) break; if (p + p->_size == q->_ptr) { p->_size += q->_ptr->_size; p->_ptr = q->_ptr->_ptr; } else p->_ptr = q->_ptr; if (q + q->_size == p) { q->_size += p->_size; q->_ptr = p->_ptr; } else q->_ptr = p; _allocp = q; } #define HEAPSIZE 1000 char *sbrk(n) unsigned n; { static char *p, heap[HEAPSIZE], *heap_ptr=heap; if (heap_ptr+n > heap+HEAPSIZE) return ERROR; p=heap_ptr; heap_ptr += n; return p; } exit(n) { fclose(9); fclose(10); _exit(n); } _exit(n) { if (n) printf("\nERROR EXIT %d", n); else printf("\nEXIT OK"); printf("\nPlease press any key"); rawin(); inline(0xC3, 67,0); } /* Pseudo-Random Number Generator */ /* Adapted from "Learning to Program in C" by Thomas Plum. */ char _rnum[4]; void srand(n) { long_init(_rnum, 0,n); } int rand() { static char k[4]; long_init(k, 0x41c6,0x4e6d); long_multiply(_rnum, _rnum, k); long_init(k, 0,0x3039); long_add(_rnum, _rnum, k); return ((_rnum[3] << 8) + _rnum[2]) & 0x7FFF; } /* Some Functions for 32 bit integer arithmetic */ void long_multiply(c, a, b) char *a, *b, *c; { static char x[4], product[4]; static int i, j; long_set(product, 0,0); for (i = 0; i < 4; ++i) for (j = i; j >= 0; --j) { long_set(x, a[i-j] * b[j], i); long_add(product, product, x); } long_copy(c, product); } void long_add(c, a, b) char *a, *b, *c; { static unsigned u, i; u = 0; for (i = 0; i < 4; ++i) { u += *a++ + *b++; *c++ = u & 0xff; u >>= 8; } } void long_init(a, n1, n0) char *a; unsigned n1,n0; { a[0] = n0 & 0xff; a[1] = n0 >> 8; a[2] = n1 & 0xff; a[3] = n1 >> 8; } void long_set(a, n, d) char *a; unsigned n, d; { static int i; for (i=0; i<4; ++i) a[i] = 0; a[d] = n & 0xff; if (d < 3) a[d+1] = n >> 8; } void long_copy(c, a) char *a, *c; { blt(c, a, 4); } #list+ /*****************************/ /* Hisoft C */ /* Standard Function Library Track-Info  N A B C D E F G H I*/ /* End */ /*****************************/ dard Function Library */ /* version 1.2 2] = n1 & 0xff; a[3] = n1 >> 8; } void long_set(a, n, d) char *a; unsigned n, d; { static int i; for (i=0; i<4; ++i) a[i] = 0; a[d] = n & 0xff; if (d < 3) a[d+1] = n >> 8; } void long_copy(c, a) char *a, *c; { blt(c, a, 4); } #list+ /*****************************/ /* Hisoft C */ /* Standard Function Library /* * * * * * B A S I C 2 . L I B * * * * * */ /* */ /* Graphics Function Library */ /* Copyright (C) 1985 HISOFT */ /* Last Changed 9 June 1985 */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * */ #list- draw(control_string) char *control_string; { #define _DRAW_SCALE 2 typedef int *ip; typedef char *cp; static int *p, c, heading, dx, dy, dX, dY, x_scale = 1 << _DRAW_SCALE, y_scale = 1 << _DRAW_SCALE; static char *s, *s2; s = control_string; while (c = tolower(*s)) { ++s; p = cast(ip) s; dX = *p++ * x_scale >> _DRAW_SCALE; dY = *p++ * y_scale >> _DRAW_SCALE; s2 = cast(cp) p; switch (heading) { case 0: dx = dX; dy = dY; break; case 1: dx = dY; dy = -dX; break; case 2: dx = -dX; dy = -dY; break; case 3: dx = -dY; dy = dX; break; } switch (c) { default: continue; case '0': G_move_absolute(0, 0); s2 = s; break; case 'm': G_move_relative(dx, dy); break; case 'p': G_plot_relative(dx, dy); break; case 'l': G_line_relative(dx, dy); break; case 't': while (*s != '\n') G_wr_char(*s++); s2 = s + 1; break; case 'c': if (tolower(*s++) == 'f') G_set_pen(*s); else G_set_paper(*s); s2 = s + 1; break; case 's': x_scale = dx; y_scale = dy; break; case 'r': heading = (heading + 1) % 4; s2 = s; break; } s = s2; } } T_set_graphic(on) { reg_a = on; inline( LD_A_from, ®_a, CALL, 0xBB63 /* TXT_SET_GRAPHIC */ ); } T_win_enable(x1,x2,y1,y2) { reg_hl = (x1 << 8) + y1; reg_de = (x2 << 8) + y2; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, CALL, 0xBB66 /* TXT_WIN_ENABLE */ ); } T_swap_streams(stream_number, another_stream_number) { reg_bc = (stream_number << 8) + another_stream_number; inline( LD_BC_from, ®_bc, CALL, 0xBBB7 /* TXT_SWAP_STREAMS */ ); } T_get_cursor(px_column, py_row, p_roll_count) int *px_column, *py_row, *p_roll_count; { inline( CALL, 0xBB78, /* TXT_GET_CURSOR */ LD_A_into, ®_a, LD_HL_into, ®_hl ); *p_roll_count = reg_a; *px_column = (reg_hl >> 8) & 0xFF; *py_row = reg_hl & 0xFF; } G_ask_cursor(pdx, pdy) int *pdx, *pdy; { inline( CALL, 0xBBC6, /* GRA_ASK_CURSOR */ LD_DE_into, ®_de, LD_HL_into, ®_hl ); *pdx = reg_de; *pdy = reg_hl; } G_set_origin(x,y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBC9 /* GRA_SET_ORIGIN */ ); } G_win_width(x1,x2) { reg_de = x1; reg_hl = x2; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBCF /* GRA_WIN_WIDTH */ ); } G_win_height(y1,y2) { reg_de = y1; reg_hl = y2; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBD2 /* GRA_WIN_HEIGHT */ ); } G_clear_window() { inline(CALL, 0xBBDB); /* GRA_CLEAR_WINDOW */ } Track-Info  N A B C D E F G H I G_set_pen(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBBDE /* GRA_SET_PEN */ ); } G_set_paper(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBBE4 /* GRA_SET_PAPER */ ); } G_wr_char(c) { reg_a = c; inline( LD_A_from, ®_a, CALL, 0xBBFC /* GRA_WR_CHAR */ ); } G_move_absolute(x,y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBC0 /* GRA_MOVE_ABSOLUTE */ ); } G_move_relative(dx, dy) { reg_de = dx; reg_hl = dy; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBC3 /* GRA_MOVE_RELATIVE */ ); } G_plot_absolute(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBEA /* GRA_PLOT_ABSOLUTE */ ); } G_plot_relative(dx, dy) { reg_de = dx; reg_hl = dy; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBED /* GRA_PLOT_RELATIVE */ ); } int G_test_absolute(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBF0, /* GRA_TEST_ABSOLUTE */ LD_L_A, LD_H_with, 0 ); } int G_test_relative(dx, dy) { reg_de = dx; reg_hl = dy; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBF3, /* GRA_TEST_RELATIVE */ LD_L_A, LD_H_with, 0 ); } G_line_absolute(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBF6 /* GRA_LINE_ABSOLUTE */ ); } G_line_relative(dx, dy) { reg_de = dx; reg_hl = dy; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBF9 /* GRA_LINE_RELATIVE */ ); } #list+ /* * * * * * End of Graphics VDU Functions * * * * * */  /* * * * * * B A S I C 1 . L I B * * * * * */ /* */ /* Copyright (C) 1985 by HISOFT */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * */ #list- /* * * * * * SOUND FUNCTIONS * * * * * */ #define MAXCHAN 3 /* number of channels */ #define CHIP_QUEUE 5 /* The chip can queue 5 notes */ #define SOFT_QUEUE 100 /* Max length of play string for each channel Alter to suit but MAKE ENOUGH ROOM */ typedef struct { char _sp_status; char _sp_amp_env; char _sp_ton_env; unsigned _sp_note; char _sp_noise; char _sp_volume; unsigned _sp_duration; /* A standard sound block up to here as BASIC */ char _sp_octave; char _sp_tempo; } sound_program, *_sp_ptr; typedef struct { int _q_in_pointer; int _q_out_pointer; unsigned _q_free_space; unsigned _q_newly_added; char _q_buffer[SOFT_QUEUE]; } _queue_data, *_queue_ptr; typedef struct { char _se_event[12]; _queue_data _se_q_data; sound_program _s_prog; } _se_block, *_seb_ptr; /* The whole event block + data */ int _s_q_char; setup_sound() { extern int _sound_event(); extern _seb_ptr _get_seb_addr(); static char i; static _queue_ptr qp; static _sp_ptr sp; static _seb_ptr sebi; inline(CALL, 0xBCA7); /* SOUND RESET */ for (i=0; i<3; i++) { sebi = _get_seb_addr(i); qp = & sebi->_se_q_data; qp->_q_in_pointer = qp->_q_out_pointer = qp->_q_newly_added = 0; qp->_q_free_space = SOFT_QUEUE; sp = & sebi->_s_prog; sp->_sp_status = (1 << i); sp->_sp_amp_env = sp->_sp_ton_env = sp->_sp_note = sp->_sp_noise = sp->_sp_duration = 0; sp->_sp_volume = 15; sp->_sp_octave = 3; sp->_sp_tempo = 25; init_event(sebi, _sound_event); } } play(controTrack-Info  N A B C D E F G H Il_string,status) char *control_string,status; { extern _seb_ptr _get_seb_addr(); static _queue_ptr ptr; static int channel, c; static _seb_ptr this_seb; for (channel=2; channel>=0; --channel) if (status & (1 << channel)) { this_seb = _get_seb_addr(channel); ptr = &this_seb->_se_q_data; _s_putq('S',ptr); _s_putq(status,ptr); while (c = (*control_string++)) _s_putq(c,ptr); /* Put the string into the buffer */ _s_syncq(this_seb); /* Tell the event routine about the string */ } } /* Put a character into the play string if there's space */ _s_putq(c,ptr) _queue_ptr ptr; { while ( ! (ptr->_q_free_space - ptr->_q_newly_added)); ptr->_q_buffer[ptr->_q_in_pointer] = c; ptr->_q_in_pointer = (ptr->_q_in_pointer + 1) % SOFT_QUEUE; ptr->_q_newly_added++; } /* Set the pointers after adding characters to the string and re-arm the sound event if the queue was empty to start with */ _s_syncq(this_seb) _seb_ptr this_seb; { static _queue_ptr ptr; static unsigned free; ptr = &this_seb->_se_q_data; inline(DI); free = ptr->_q_free_space; ptr->_q_free_space = free - ptr->_q_newly_added; ptr->_q_newly_added = 0; inline(EI); if (free == SOFT_QUEUE) S_arm_event(this_seb->_s_prog._sp_status, this_seb); } /* event routine gets the next note and puts it on the queue */ _sound_event(event_address) unsigned event_address; { _queue_ptr ptr; _sp_ptr sp; _seb_ptr this_seb; int ti, got; this_seb = cast(_seb_ptr) (event_address - 4); ptr = &this_seb->_se_q_data; sp = &this_seb->_s_prog; got = 1; sp->_sp_status &= 7; _s_getq(ptr); while (_s_q_char != '.') { if (got) got = 0; else _s_getq(ptr); switch (_s_q_char) { case 'S' : sp->_sp_status |= _s_getq(ptr) & 0xF8; break; case 'V' : sp->_sp_volume = _s_getq(ptr); break; case 'N' : sp->_sp_noise = _s_getq(ptr); break; case 'Y' : sp->_sp_amp_env = _s_getq(ptr); break; case 'Z' : sp->_sp_ton_env = _s_getq(ptr); break; case 'O' : sp->_sp_octave = _s_getq(ptr) & 7 ; break; case 'T' : sp->_sp_tempo = (1500 / _s_getq(ptr)); break; default : if ((ti = _getnote(this_seb)) == 1) break; sp->_sp_note = ti; if (_s_q_char < ' ') ti = _s_q_char; else {ti = 4; got = 1;} sp->_sp_duration = sp->_sp_tempo * ti; } } _do_queue(sp); if (ptr->_q_free_space != SOFT_QUEUE) S_arm_event(sp->_sp_status & 7, this_seb); } _getnote(this_seb) _seb_ptr this_seb; { int note,t_octave; _queue_ptr ptr; static unsigned period[] = /* The values for the periods of the notes */ {0,2551,2408,2273,2145,2025,1911,1804,1703,1607,1517,1432,1351,1276,1204,1136}; /* A B C D E F G */ ptr = &this_seb->_se_q_data; t_octave = this_seb->_s_prog._sp_octave; if (_s_q_char == '\'') t_octave -= _oct_factor(ptr); switch(_s_q_char) { default : return 1; /* an error */ case 'W' : note = 0; break; case 'A' : note = 3; break; case 'B' : note = 5; break; case 'C' : note = 6; break; case 'D' : note = 8; break; case 'E' : note =10; break; case 'F' : note =11; break; case 'G' : note =13; } _s_getq(ptr); do if (_s_q_char == '#') {note++; _s_getq(ptr);} else if (_s_q_char == 'b') {note--; _s_getq(ptr);} else break; while (1); if (_s_q_char == '\'') t_octave += _oct_factor(ptr); return period[note] >> t_octave; } _do_queue(sp) _sp_ptr sp; { int channel,qpos,chanbit; _sp_ptr dest_q; static char q_flag[] = {4,4,4}; static sound_program spra[MAXCHAN][CHIP_QUEUE]; chanbit = sp->_sp_status & 7; if (chanbit > 3) {channel = 2; chanbit = 4;} else if (chanbit > 1) {channel = 1; chanbit = 2;} else channel = 0; qpos = ++q_flag[channel] % CHIP_QUEUE; dest_q = &spra[channel][qpos]; while ( ! (sound_check(chanbit) & 7)); blt(dest_q, sp, sizeof(sound_program)-2); S_queue(dest_q); } _oct_factor(ptr) _queue_ptr ptr; { int oct; oct = 1; while (_s_getq(ptr) == '\'') ++oct; return oct; } _s_getq(ptr) _queue_ptr ptr; { _s_q_char = ptr->_q_buffer[ptr->_q_out_pointer]; ptr->_q_out_pointer = (ptr->_q_out_pointer + 1) % SOFT_QUEUE; ptr->_q_free_space++; return _s_q_charTrack-Info  N A B C D E F G H I; } _seb_ptr _get_seb_addr(i) { static _se_block s_event_block[MAXCHAN]; return &s_event_block[i]; } S_arm_event(channel_bit,seb_add) { reg_a = channel_bit; reg_hl = seb_add; inline( LD_A_from, ®_a, LD_HL_from,®_hl, CALL, 0xBCB0); /* SOUND_ARM_EVENT */ } S_queue(sp) { reg_hl = sp; inline( LD_HL_from, ®_hl, PUSH_IX, CALL, 0xBCAA, /* SOUND_QUEUE */ POP_IX, LD_HL_with, 0,0, RL_L); } sound_check(chanbit) char chanbit; { reg_a = chanbit; inline( LD_A_from, ®_a, CALL, 0xBCAD, /* SOUND_CHECK */ LD_A_into, ®_a); return reg_a; } S_release(channel_bits) { reg_a = channel_bits; inline( LD_A_from, ®_a, PUSH_IX, CALL, 0xBCB3, /* SOUND_RELEASE */ POP_IX); } S_ampl_envelope(number, envelope) { reg_a = number; reg_hl = envelope; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBCBC); /* SOUND_AMPL_ENVELOPE */ } S_tone_envelope(number, envelope) { reg_a = number; reg_hl = envelope; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBCBF); /* SOUND_TONE_ENVELOPE */ } S_hold() { inline( CALL, 0xBCB6, /* SOUND_HOLD */ LD_HL_with, 0,0, RL_L); } S_continue() { inline( PUSH_IX, CALL, 0xBCB9, /* SOUND_CONTINUE */ POP_IX); } /* The next function cures a ROM problem and should be called if and only if: the program is being compiled on a CPC464, and it uses "play()", and it is being #translated. */ fix_464_sound_interrupts() { static char tick_block[13], sync_q[] = { 0xF5, 0xC5, 0xD5, 0xE5, 0xCD, 0x21, 0xB9, 0x30, 0x11, 0xCD, 0xFB, 0xBC, 0x30, 0x0C, 0xE5, 0xF5, 0xCD, 0xFE, 0xBC, 0xF1, 0xE1, 0xCD, 0x01, 0xBD, 0x18, 0xEF, 0xE1, 0xD1, 0xC1, 0xF1, 0xC9}; inline( 0x21, tick_block, 0xCD, 0xBCEC, 0x21, 6+cast(int)tick_block, 0x01, 0x80FF, 0x11, sync_q, 0xCD, 0xBCEF, 0x21, tick_block, 0x11, 2,0, 0x01, 5,0, 0xCD, 0xBCE9); } after(delay_in_ticks, control_block, function_name) { add_ticker(control_block, delay_in_ticks, 0, function_name); } every(period_in_ticks, control_block, function_name) { add_ticker(control_block, period_in_ticks, period_in_ticks, function_name); } add_ticker(ctrl_block, initial_time_delay, recharge_delay, function_name) { init_event(ctrl_block + 6, function_name); reg_hl = ctrl_block; reg_de = initial_time_delay; reg_bc = recharge_delay; /* 0 is one-shot */ inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBCE9); /* KL_ADD_TICKER */ } init_event(event_block, function_name) { typedef char *cp; typedef unsigned *up; static up p; reg_hl = event_block; /* start of event block */ reg_bc = 0x80FF; /* asynchronous, all RAM */ reg_de = reg_hl + 7; /* event routine at end of block */ p = cast(up) reg_de; /* to poke code for routine */ *p = 0xCDE5; /* PUSH_HL; CALL ... */ *++p = function_name; /* ... the real function */ *cast(cp)++p = 0xC9; /* and return to interrupted code */ inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBCEF); /* KL_INIT_EVENT */ } border(colour1, colour2) { reg_bc = (colour1 << 8) + colour2; inline( LD_BC_from, ®_bc, CALL, 0xBC38); /* SCR_SET_BORDER */ } cass_speed(speed) { if ( ! speed) inline( LD_HL_with, 333, LD_A_with, 25, CALL, 0xBC68); /* CAS_SET_SPEED */ if (speed == 1) inline( LD_HL_with, 167, LD_A_with, 50, CALL, 0xBC68); /* CAS_SET_SPEED */ } catalog() { char cas_buffer[2048]; reg_de = cast(unsigned) cas_buffer; inline( LD_DE_from, ®_de, PUSH_IX, CALL, 0xBC9B, /* CAS_CATALOG */ POP_IX); } cls() { rawout('\f'); } event_disable() { inline(CALL, 0xBD04); /* KL_EVENT_DISABLE */ } event_enable() { inline(CALL, 0xBD07); /* KL_EVENT_ENABLE */ } flash_speed(time1, time2) { reg_hl = (time1 << 8) + time2; inline( LD_HL_from, ®_hl, CALL, 0xBC3E); /* SCR_SET_FLASHING */ } ink(ink_to_setup, colour1, colour2) { reg_a = ink_to_setup; reg_bc = (colTrack-Info  NABCDEFGHIour1 << 8) + colour2; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBC32); /* SCR_SET_INK */ } int inkey(key_number) { reg_a = key_number; inline( LD_A_from, ®_a, CALL, 0xBB1E, /* KM_TEST_KEY */ LD_B_with, 0, JR_Z, 1, INC_B, LD_BC_into, ®_bc); return (reg_bc & 0x100) ? (reg_bc & 0xA0) : -1; } char *instr(main_string, sub_string) char *main_string, *sub_string; { static int length; length = strlen(sub_string); do if ( ! strncmp(main_string, sub_string, length)) return main_string; while (*++main_string); return 0; /* == NULL */ } itob(n, string, precision) char *string; { static int i, c; static char *s; s = string; for (i=precision; i; ) *s++ = n & (1 << --i) ? '1' : '0'; *s = 0; return cast(int)string; } joy(joystick_number) { inline( CALL, 0xBB24, /* KM_GET_JOYSTICK */ LD_HL_into, ®_hl); return (joystick_number ? reg_hl : (reg_hl >> 8)) & 0xFF ; } int key_function(translated_key_number, expansion_string) { reg_bc = (translated_key_number << 8) + (strlen(expansion_string) & 0xFF); reg_hl = expansion_string; inline( LD_BC_from, ®_bc, LD_HL_from, ®_hl, CALL, 0xBB0F, /* KM_SET_EXPAND */ LD_A_with, 0, RLA, LD_A_into, ®_a); return reg_a; } key_speed(start_up_delay, time_between_repeats) { reg_hl = (start_up_delay << 8) + time_between_repeats; inline( LD_HL_from, ®_hl, CALL, 0xBB3F); /* KM_SET_DELAY */ } key_translation(key_number, translated_key_number) { reg_a = key_number; reg_bc = translated_key_number << 8; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBB27); /* KM_SET_TRANSLATE */ } K_arm_breaks(event_routine, ROM_select) { reg_de = event_routine; reg_bc = ROM_select; inline( LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBB45); /* KM_ARM_BREAKS */ } K_disarm_break() { inline(CALL, 0xBB48); /* KM_DISARM_BREAK */ } read_file(filename, address) char *filename, *address; { int c; FILE *file_pointer; if ( ! (file_pointer = fopen(filename,"r"))) { fprintf(stderr,"\nERROR - Cannot open file :%s:\n",filename); return ERROR; } while ((c = getc(file_pointer)) != EOF) *address++ = c; fclose(file_pointer); return TRUE; } char *strlower(string) char *string; { static char *s; static int c; for (s = string; c = *s; ++s) *s = tolower(c); return string; } char *strupper(string) char *string; { static char *s; static int c; for (s = string; c = *s; ++s) *s = toupper(c); return string; } symbol(character_number, matrix) { reg_a = character_number; reg_hl = matrix; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBBA8); /* TXT_SET_MATRIX */ } symbol_after(number, table_memory) { reg_de = number; reg_hl = table_memory; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBAB); /* TXT_SET_M_TABLE */ } time(array) int array[2]; { inline( CALL, 0xBD0D, /* KL_TIME_PLEASE */ LD_DE_into, ®_de, LD_HL_into, ®_hl); array[0] = reg_hl; array[1] = reg_de; } write_file(filename, address, length) char *filename, *address; unsigned length; { FILE *file_pointer; if ( ! (file_pointer = fopen(filename, "w"))) { fprintf(stderr, "\nERROR - Cannot open file :%s:\n", filename); return ERROR; } while (length--) putc(*address++, file_pointer); fclose(file_pointer); return TRUE; } #list+ /* * * * * * E N D O F B A S I C 1 . L I B * * * * * */  fclose(file_pointer); return TRUE; } #list+ /* * * * * e, address, length) char *filename, *address; unsigned length; { FILE *file_pointer; if ( ! (file_pointer = fo/* * * * * * E X T C M D . H * * * * * */ /* */ /* allow external (bar) commands in a C program */ /* Copyright (C) 1985 HiSoft */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * */ extcmd(param_byte_count) auto { typedef char ** cpp; static char com_name[16], *s, *d; static unsigned reg_ix; reg_a = param_byte_count/2 - 2; /* no of args of command */ rTrack-Info  NABCDEFGHIeg_ix = cast(int) ¶m_byte_count + 2; /* addr of last arg */ s = *cast(cpp)(reg_ix + reg_a*2); d = com_name; do *d++ = toupper(*s++); while (*s); *--d |= 0x80; inline( LD_HL_with, com_name, CALL, 0xBCD4, /* KL_FIND_COMMAND */ PUSH_IX, LD_IX_from, ®_ix, JR_NC, 10, LD_A_from, ®_a, PUSH_IY, CALL, 0x1B,0, /* LO_KL_FAR_PCHL */ POP_IY, POP_IX ); } struct _dscrp { char _length; char *_start; }; int makestr(s,d) char *s; struct _dscrp *d; { static char *p; p = s; do ; while (*p++); d->_length = p-s-1; d->_start = s; return d; } /* End of External Command Handling */  do ; while (*p++); d->_length = p-s-1; IND_COMMAND */ PUSH_IX, LD_IX_from, ®_ix, JR_NC, 10, LD_A_from, ®_a, PUSH_IY, CALL, 0x1B,0, /* LO_KL_FAR_PCHL */ POP_IY, POP_IX ); } struct _dscrp { char _length; char *_start; }; i/*****************************/ /* Hisoft C */ /* Standard Function Library */ /* HEADER */ /* */ /* Copyright (C) 1984 Hisoft */ /* Last changed 5 Jun 1985 */ /*****************************/ #list- #define NULL 0 /* for use with pointers */ #define FALSE 0 /* for Boolean operations */ #define TRUE 1 #define EOF -1 /* end of file value */ #define ERROR -1 #define void int /* for functions which return no value */ #define stdin 0 #define stdout 0 #define stderr 0 #define LD_A_from 0x3A #define LD_A_into 0x32 #define LD_A_with 0x3E #define LD_HL_from 0x2A #define LD_HL_into 0x22 #define LD_HL_with 0x21 #define LD_DE_from 0x5BED #define LD_DE_into 0x53ED #define LD_BC_from 0x4BED #define LD_BC_into 0x43ED #define LD_IX_from 0x2ADD #define RLA 0x17 #define LD_L_A 0x6F #define LD_H_with 0x26 #define RL_L 0x15CB #define CALL 0xCD #define LD_B_with 0x06 #define JR_Z 0x28 #define JR_NC 0x30 #define INC_B 0x04 #define PUSH_IX 0xE5DD #define POP_IX 0xE1DD #define PUSH_IY 0xE5FD #define POP_IY 0xE1FD #define CALL 0xCD #define DI 0xF3 #define EI 0xFB /* File system Structure */ typedef int FILE; /* Storage Allocation Structure and Variables */ struct _header { struct _header * _ptr; unsigned _size; }; typedef struct _header HEADER, * HEADER_PTR; HEADER _base, *_allocp; /* Z80 register cache for inline code */ unsigned reg_hl, reg_de, reg_bc; char reg_a; /* Forward declarations for non-int library functions */ extern char *strcat(), *strncat(), *strcpy(), *strncpy(), *strchr(), *strrchr(), *strpbrk(), *calloc(), *sbrk(), *fgets(),*gets(); extern unsigned strlen(); /* Two variadic arithmetic functions (see manual for details) */ int max(param_byte_count) auto { static int argc, *argv, max; argc = param_byte_count/2 - 1; argv = ¶m_byte_count + argc; max = -32767; while (argc--) { if (*argv > max) max = *argv; --argv; } return max; } int min(param_byte_count) auto { static int argc, *argv, min; argc = param_byte_count/2 - 1; argv = ¶m_byte_count + argc; min = 32767; while (argc--) { if (*argv < min) min = *argv; --argv; } return min; } #list+ /*****************************/ /* Hisoft C */ /* Standard Function Library */ /* End Header */ /*****************************/  Hisoft C *argv; --argv; } return max; } int min(param_byte_count) auto { static int argc, *argv, min; argc = param_byte_count/2 - 1; argv = ¶m_byte_count + argc; min = 32767; while (argc--) { if (*argv < min) min = *argv; --argv; } return min; } #list+ /*****************************/ /* Hisoft C Track-Info  NABCDEFGHI/* OTHELLO (REVERSI) PROGRAM */ /* First are the standard library functions which are used */ int abs(n) { return n<0 ? -n : n ; } /* Sorting function - a Shell sort */ qsort(list, num_items, size, cmp_func) char *list; int num_items, size; int (*cmp_func)(); { static unsigned gap, byte_gap, i; static char *p; for (gap = num_items >> 1; gap > 0; gap >>= 1) { byte_gap = gap * size; for (i = gap; i < num_items; ++i) for (p = list + i * size - byte_gap; p >= list; p -= byte_gap) { if ((*cmp_func)(p, p + byte_gap) <= 0) break; swap(p, p + byte_gap, size); } } } puts(s) char *s; { static int c; while(c=*s++)putchar(c); } /* Pseudo-Random Number Generator */ /* Adapted from "Learning to Program in C" by Thomas Plum. */ char _rnum[4]; srand(n) { long_init(_rnum, 0,n); } int rand() { static char k[4]; long_init(k, 0x41c6,0x4e6d); long_multiply(_rnum, _rnum, k); long_init(k, 0,0x3039); long_add(_rnum, _rnum, k); return (_rnum[1] << 8) + _rnum[0]; } /* Some Functions for 32 bit integer arithmetic */ long_multiply(c, a, b) char *a, *b, *c; { static char x[4], product[4]; static int i, j; long_set(product, 0,0); for (i = 0; i < 4; ++i) for (j = i; j >= 0; --j) { long_set(x, a[i-j] * b[j], i); long_add(product, product, x); } long_copy(c, product); } long_add(c, a, b) char *a, *b, *c; { static unsigned u, i; u = 0; for (i = 0; i < 4; ++i) { u += *a++ + *b++; *c++ = u & 0xff; u >>= 8; } } long_init(a, n1, n0) char *a; unsigned n1,n0; { a[0] = n0 & 0xff; a[1] = n0 >> 8; a[2] = n1 & 0xff; a[3] = n1 >> 8; } long_set(a, n, d) char *a; unsigned n, d; { static int i; for (i=0; i<4; ++i) a[i] = 0; a[d] = n & 0xff; if (d < 3) a[d+1] = n >> 8; } long_copy(c, a) char *a, *c; { blt(c, a, 4); } /* OTHELLO -- The Game of Dramatic Reversals written by Bert Halstead modified for BDS C by Leor Zolman modified for Hisoft C by Dave Howorth - correct some function type errors - remove an & from call to qsort (its not right on an array) - change to unix-style rand() function - make variables static to save hundreds of bytes This program is a good example of: a) structured, heirarchical function organization b) arrays as formal parameters c) use of the "qsort" library function d) non-standards ( eg & on array name as actual parameters!) Object of the game is for two players to alternate placing their marker someplace on an 8 by 8 grid, so that at least one of the opponent's pieces becomes surrounded by the moving player's peices -- causing the flanked pieces to flip 'color' and belong to the moving player. After 60 moves have been played (or if no player has a legal move left), the player with the most of his own pieces on the board wins. The playing pieces are '*' and '@'. You may choose to play either '*' or '@' for the first game; thereafter, you and the computer will alternate going first for each game. Whoever goes first always plays `*'. You enter a move as a two digit number, each digit being from 1 to 8, first digit representing row and second representing column. For example: if playing '*', your first move might be '46', meaning 4th row down, 6th position across. As an alternative to entering a move, one of the following commands may be typed: g causes computer to play both sides until game is over or until you hit a key. a causes computer to print out an analysis of each of your possible moves. A letter from A to Z will appear at each of your legal move positions, where A is the machine's opinion of an excellant move and Z is a real loser. hn sets handicap. n is 1,2,3, or 4. If n is positive, gives n free pieces to the computer. If n is negative, gives YOU the free peices. f forfeit the current move. This happens automatically if you have no legal moves. q quit the current game. b prints out board again. s prints out the score, and tells who is winning. */ #define NULL 0 #define TRUE 1 #define FALSE 0 #define BLACK '*' #define WHITE '@' #define EMPTY '-' char selfplay; /* true if computer playing with itself */ char mine, his; Track-Info  NABCDEFGHI/* who has black (*) and white (@) in current game */ main(argc,argv) int argc; char **argv; { static char b[8][8]; static int i; static char mefirst; /* true if computer goes first in current game */ printf("\n\nWelcome to the Hisoft C OTHELLO program!\n"); printf("\nNote: `*' always goes first...Good luck!!!\n\n"); puts("Do you want to go first? "); mefirst = (toupper(rawin()) != 'Y'); printf("\n\n"); do { clrbrd(b); prtbrd(b); i = game(b,4,mefirst); mefirst = !mefirst; if (i==4) break; if (i=='Q') continue; printf("\n"); i = prtscr(b); if (i>0) printf(" You won by %d\n",i); else if (i<0) printf(" You lost by %d\n",-i); else printf(" A draw\n"); } while (ask("Another game? ")=='Y'); } game(b,n,mefirst) char b[8][8]; int n; { static char c; static int ff; static int i,j; static int handicap; static int h[4][2] = {0, 0, /* handicap position table */ 7, 7, 0, 7, 7, 0}; handicap = 0; selfplay = ' '; ff=0; if (mefirst) { mine = BLACK; his = WHITE; printf("\nI go first:\n\n"); } else { mine = WHITE; his = BLACK; printf("\nYou go first:\n\n"); } while(1) { if (cntbrd(b,EMPTY)==0) return 'D'; if (cntbrd(b,EMPTY)==60 && mine == BLACK) goto Istart; if (chkmvs(b,his)==0) { printf(!mefirst ? "Forfeit" : " ...Forfeit\n"); ff |= 1; } else switch (c = getmov(&i,&j)) { case 'B': prtbrd(b); continue; case 'S': i= prtscr(b); if (i>0) printf(" You're winning\n"); else if (i<0)printf(" You're losing!\n"); else putchar('\n'); continue; case 'Q': case 4: return c; case 'H': if (n>abs(handicap)+4) printf("Illegal!\n"); else for (j=0; i!=0; j++) { b[h[j][0]][h[j][1]]= i>0?BLACK:WHITE; handicap += i>0 ? 1 : -1; ++n; i += i>0 ? -1 : 1; } prtbrd(b); continue; case 'A': analyze(b,his,mine,EMPTY); continue; case 'G': my_mov(b,his,mine,EMPTY,&i,&j); case 'M': if (chkmov(b,his,i,j)>0) { printf(!mefirst ? "%1d-%1d" : " ...%1d-%1d\n", i+1,j+1); putmov(b,his,i,j); } else { printf("Illegal!\n"); continue; } break; case 'F': if (n>abs(handicap)+4) { printf ("Illegal!\n"); continue; } else printf(!mefirst ? "Forfeit" : " ...Forfeit\n"); } Istart: if (cntbrd(b,EMPTY) == 0) return 'D'; if (chkmvs(b,mine)==0) { printf(!mefirst ? "...Forfeit\n": "Forfeit...\n"); ff |=2; } else { my_mov(b,mine,his,EMPTY,&i,&j); printf(!mefirst ? "...%1d-%1d\n" : "%1d-%1d...\n", i+1,j+1); putmov(b,mine,i,j); ++n; } if (ff==3 || n>64) return 'D'; if (!(ff & 1)) prtbrd(b); ff = 0; } } /* second half of Othello progrram */ prtscr(b) char *b; { static int i,j; printf("%1d-%1d",i = cntbrd(b,his), j=cntbrd(b,mine)); return i-j; } int getmov(i,j) int *i, *j; { static char a,c; static int n; static char *p; if (selfplay == 'G') { if (!keyhit()) return 'G'; selfplay = ' '; getchar(); } printf("Move: "); while(1) switch (c=skipbl()) { case '\n': printf("Move? "); continue; case 'G': if ((c = skipbl()) != '\n') goto flush; selfplay='G'; return 'G'; case 'B': case 'S': case 'Q': case 'F': case 'A': a=c; if (( c = skipbl()) != '\n') goto flush; return a; case 'H': if ((a=c=skipbl()) == EMPTY) c=getchar(); if (c<'1' || c>'4' || skipbl() !='\n') goto flush; *i = a==EMPTY? -(c-'0') : (c-'0'); return 'H'; case 4: return c; default: if (c<'1' || c>'8') goto flush; *i = c-'1'; c = skipbl(); if (c<'1' || c>'8') goto flush; *j = c- '1'; if ((c=skipbl()) == '\n') return 'M'; flush: while (c != '\n' && c != 4) c=getchar(); if (c==4) return c; printf ("Huh?? "); } } int ask(s) char *s; { char a,c; printf ("%s ",s); a=skipbl(); while (c != '\n' && c != 4) c= getchar(); return a; } int skipbl() { static char c; while ((c = toupper(getchar())) == ' ' || c=='\t'); return c; } chkmvs(b,p) char b[8][8]; char p; { static int i,j,k; k=0; for (i=0; i<8; i++) for (j=0; j<8; j++) k += chkmov(b,p,i,j); return k; } chkmov(b,p,x,y) char b[8][8],p; int x,y; { if (b[x][y] != EMPTY) return 0; return chkmv1(b,p,x,y,0,1) + chkmv1(b,p,x,y,1,0) + chkmv1(b,p,x,y,0,-1)+ chkmv1(b,p,x,y,-1,0)+ chkmv1(b,Track-Info  NABCDEFGHIp,x,y,1,1) + chkmv1(b,p,x,y,1,-1)+ chkmv1(b,p,x,y,-1,1)+ chkmv1(b,p,x,y,-1,-1); } chkmv1(b,p,x,y,m,n) char b[8][8],p; int x,y,m,n; { static int k; k=0; while ((x += m) >= 0 && x < 8 && (y += n) >= 0 && y<8) { if (b[x][y]==EMPTY) return 0; if (b[x][y]== p ) return k; if (x==0 || x==7 || y==0 || y==7) k += 10; else k++; } return 0; } notake(b,p,o,e,x,y) char b[8][8]; char p,o,e; int x,y; { return notak1(b,p,o,e,x,y,0,1)&& notak1(b,p,o,e,x,y,1,1)&& notak1(b,p,o,e,x,y,1,0)&& notak1(b,p,o,e,x,y,1,-1); } notak1(b,p,o,e,x,y,m,n) char b[8][8],p,o,e; int x,y,m,n; { static int c1,c2; c1 = notak2(b,p,o,e,x,y,m,n); c2 = notak2(b,p,o,e,x,y,-m,-n); return !(c1==o && c2==e || c1==e && c2==o); } notak2(b,p,o,e,x,y,m,n) char b[8][8],p,o,e; int x,y,m,n; { x += m; y +=n; if (x>=0 && x<=7 && y>=0 && y<=7) while(b[x][y] == 0) { x += m; y+=n; if (x<0 || x>7 || y<0 || y>7 || b[x][y]==e) return o; } while (x>=0 && x<=7 && y>=0 && y<=7 && b[x][y]==p) { x +=m; y+=n; } if (x<0 || x>7 || y<0 || y>7) return p; return b[x][y]; } putmov(b,p,x,y) char b[8][8]; char p; int x,y; { static int i,j; b[x][y] = p; for (i= -1; i<=1; i++) for (j= -1; j<=1; j++) { if ((i != 0 || j!=0)&&chkmv1(b,p,x,y,i,j)>0) putmv1(b,p,x,y,i,j); } } putmv1(b,p,x,y,m,n) char b[8][8]; char p; int x,y,m,n; { while ((x += m) >= 0 && x<8 && (y += n)>=0 && y<8) { if (b[x][y] == EMPTY || b[x][y] == p) return; b[x][y] = p; } } struct mt { int x; int y; int c; int s; }; cmpmov(a,b) struct mt *a, *b; { if ((*a).s > (*b).s) return -1; if ((*a).s < (*b).s) return 1; if ((*a).c > (*b).c) return -1; if ((*a).c < (*b).c) return 1; return 0; } my_mov(b,p,o,e,m,n) char b[8][8],p; int *m, *n; { static struct mt t[64]; static int i,k; k = fillmt(b,p,o,e,t); if (!k) return 0; qsort (t, k, 8, cmpmov); for (i=1; i=10) { s -= 4; oside |= 8; } } if (s< -oside) s= -oside; if (side>0) return s+side-7+10*ok; if (i==1 || i==6) {s--; side++;} if (j==1 || j==6) {s--; side++;} if (side>0) return s; if (i==2 || i==5) s++; if (j==2 || j==5) s++; return s; } clrbrd(b) char b[8][8]; { static char empty_board[8][8] = { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BLACK, WHITE, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, WHITE, BLACK, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY}; blt(b, empty_board, 8*8); } prtbrd(b) char b[8][8]; { static int i,j; printf(" 1 2 3 4 5 6 7 8\n"); for (i=0; i<8; i++) { printf("%2d",i+1); for (j=0; j<8; j++) { putchar(' '); putchar(b[i][j]); } putchar('\n'); } pTrack-Info  NABCDEFGHIutchar('\n'); } cpybrd(a,b) char *a, *b; { static int i; i=64; while (i--) *a++ = *b++; } cntbrd(b,p) char *b, p; { static int i,j; i= 64; j=0; while (i--) if (*b++ == p) ++j; return (j); } /* END OF OTHELLO */ $RSI) PROGRAM */ /* First are the standard library functions which are used */ int abs(n) { return n<0 ? -; i++) { printf("%2d",i+1); for (j=0; j<8; j++) { putchar(' '); putchar(b[i][j]); } putchar('\n'); } p HiSoft C++ Compiler This side of the disc contains the AMSDOS compiler "HISOFT-C.BIN" The other side of the disc contains the CP/M compiler "HC.COM" You cannot run this AMSDOS version on an 8256. Enjoy yourself. Dave Howorth 3 Oct 85 in/* * * * * * F I R M W A R E . L I B * * * * * */ /* */ /* F I R M 4 - Cassette */ /* Copyright (C) 1985 HiSoft */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** CASSETTE MANAGER INTERFACE FUNCTIONS **/ /* Initialise the Cassette Manager */ C_initialise() { inline(CALL, 0xBC65); } /* Set the write speed (see BASIC.LIB) */ C_set_speed(half_zero_bit, precompensation) { reg_a = precompensation; reg_hl = half_zero_bit; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBC68); } /* Enable or disable prompt messages */ /* enable should be TRUE (1) or FALSE (0) as appropriate */ C_noisy(enable) { reg_a = ~ enable; inline( LD_A_from, ®_a, CALL, 0xBC6B); } /* Start the cassette motor */ /* returns previous motor state (whatever that is) or - pms if user pressed [ESC] */ int C_start_motor() { inline( CALL, 0xBC6E, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? reg_a : -reg_a ; } /* Stop the cassette motor */ /* returns previous motor state (whatever that is) or - pms if user pressed [ESC] */ int C_stop_motor() { inline( CALL, 0xBC71, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? reg_a : -reg_a ; } /* restore the previous state of the cassette motor */ /* returns TRUE if restored OK and FALSE if user pressed [ESC] */ int C_restore_motor(previous_motor_state) { reg_a = previous_motor_state; inline( LD_A_from, ®_a, CALL, 0xBC74, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags; } /* open a file for input */ /* use fopen() in preference. there are five or six possible return values, so customise the function for those that you need. */ C_in_open(filename, buffer) { reg_bc = strlen(filename) << 8; reg_hl = filename; reg_de = buffer; inline( LD_BC_from, ®_bc, LD_DE_from, ®_de, LD_HL_from, ®_hl, PUSH_IX, CALL, 0xBC77, POP_IX); } /* Close the input file properly */ /* returns TRUE if closed OK and FALSE if stream was not open */ int C_in_close() { inline( CALL, 0xBC7A, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags; } /* Abandon reading from the input file and close it */ C_in_abandon() { inline(CALL, 0xBC7D); } /* Read a character from the input stream */ /* returns character, or EOF (-1) if end-of-file, or -3 if user pressed [ESC] */ int C_in_char() { inline( PUSH_IX, CALL, 0xBC80, POP_IX, LD_A_into, ®_a, Track-Info  NABCDEFGHI LD_A_with, 0, RLA, JR_Z, 2, INC_A, INC_A, LD_A_into, ®_flags); return (reg_flags ^= 1) ? -reg_flags : reg_a; } /* Read the entire input file into store */ /* returns NULL (0) if OK, or EOF (-1) if end-of-file, or -3 if user pressed [ESC] */ int C_in_direct(address) { reg_hl = address; inline( LD_HL_from, ®_hl, CALL, 0xBC83, LD_A_with, 0, RLA, JR_Z, 2, INC_A, INC_A, LD_A_into, ®_flags); if (reg_flags & 1) return 0; if (reg_flags & 2) return -3; return -1; } /* Put back the last character read from cassette */ C_return() { inline(CALL, 0xBC86); } /* Test if the end of the input file has been reached */ /* returns NULL (0) if OK, or EOF (-1) if end-of-file, or -3 if user pressed [ESC] */ int C_test_eof() { inline( PUSH_IX, CALL, 0xBC89, POP_IX, LD_A_with, 0, RLA, JR_Z, 2, INC_A, INC_A, LD_A_into, ®_flags); if (reg_flags & 1) return 0; if (reg_flags & 2) return -3; return -1; } /* open a file for output */ /* use fopen() in preference. there are several possible return values, so customise the function for those that you need. */ C_out_open(filename, buffer) { reg_bc = strlen(filename) << 8; reg_hl = filename; reg_de = buffer; inline( LD_BC_from, ®_bc, LD_DE_from, ®_de, LD_HL_from, ®_hl, PUSH_IX, CALL, 0xBC8C, POP_IX); } /* Close the output file properly */ /* returns NULL (0) if OK, or ERROR (-1) if stream not open, or -3 if user pressed [ESC] */ int C_out_close() { inline( PUSH_IX, CALL, 0xBC8F, POP_IX, LD_A_with, 0, RLA, JR_Z, 2, INC_A, INC_A, LD_A_into, ®_flags); if (reg_flags & 1) return 0; if (reg_flags & 2) return -3; return -1; } /* Abandon writing to the output file and close it */ C_out_abandon() { inline(CALL, 0xBC92); } /* write a character to the output stream */ /* returns character, or ERROR (-1) if file not open, or -3 if user pressed [ESC] */ int C_out_char(character) { reg_a = character; inline( LD_A_from, ®_a, PUSH_IX, CALL, 0xBC80, POP_IX, LD_A_into, ®_a, LD_A_with, 0, RLA, JR_Z, 2, INC_A, INC_A, LD_A_into, ®_flags); if (reg_flags & 1) return 0; if (reg_flags & 2) return -3; return -1; } /* write the entire output file directly from store */ /* returns NULL (0) if OK, or ERROR (-1) if file not open or -3 if user pressed [ESC] */ C_out_direct(data_address, data_length, entry_address, file_type) { reg_hl = data_address; reg_de = data_length; reg_bc = entry_address; reg_a = file_type; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_BC_from, ®_bc, LD_A_from, ®_a, CALL, 0xBC83, LD_A_with, 0, RLA, JR_Z, 2, INC_A, INC_A, LD_A_into, ®_flags); if (reg_flags & 1) return 0; if (reg_flags & 2) return -3; return -1; } /* Generate a catalogue from the tape */ C_catalog() { char buffer[2048]; reg_de = cast (unsigned) buffer; inline( LD_DE_from, ®_de, PUSH_IX, CALL, 0xBC9B, POP_IX); } /* write a record to tape */ /* returns NULL (0) if OK and otherwise an error code: code meaning 1 the user pressed [ESC] 2 overrun in cassette manager */ int C_write(data_address, data_length, sync_character) { reg_hl = data_address; reg_de = data_length; reg_a = sync_character; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_A_from, ®_a, PUSH_IX, CALL, 0xBC9E, POP_IX, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? 0 : reg_a + 1 ; } /* read a record from tape */ /* returns NULL (0) if OK and otherwise an error code: code meaning 1 the user pressed [ESC] 2 overrun in cassette manager 3 CRC error */ int C_read(data_address, data_length, sync_character) { reg_hl = data_address; reg_de = data_length; reg_a = sync_character; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LDTrack-Info  NABCDEFGHI_A_from, ®_a, PUSH_IX, CALL, 0xBCA1, POP_IX, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? 0 : reg_a + 1 ; } /* Compare a record on tape with the contents of store */ /* returns NULL (0) if OK and otherwise an error code: code meaning 1 the user pressed [ESC] 2 overrun in cassette manager 3 CRC error 4 data on tape differs from memory */ int C_check(data_address, data_length, sync_character) { reg_hl = data_address; reg_de = data_length; reg_a = sync_character; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_A_from, ®_a, PUSH_IX, CALL, 0xBCA1, POP_IX, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? 0 : reg_a + 1 ; } /* * * * * * E N D O F F I R M 4 * * * * * */ o, ®_flags);/* * * * * * F I R M W A R E . L I B * * * * * */ /* */ /* F I R M 3 - Screen Pack */ /* Copyright (C) 1985 HiSoft */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** SCREEN PACK INTERFACE FUNCTIONS **/ /* Initialise the Screen Pack */ V_initialise() { inline(CALL, 0xBBFF); } /* Reset the Screen Pack */ V_reset() { inline(CALL, 0xBC02); } /* set the offset of the start of the screen */ V_set_offset(offset) { reg_hl = offset; inline( LD_HL_from, ®_hl, CALL, 0xBC05); } /* set the area of RAM to use for screen memory */ /* quadrant locates screen memory base as follows: 0 0x0000 1 0x4000 2 0x8000 3 0xC000 */ V_set_base(quadrant) { reg_a = (quadrant & 3) << 6; inline( LD_A_from, ®_a, CALL, 0xBC08); } /* Fetch current base and offset settings */ int V_get_offset() { inline( CALL, 0xBC0B, LD_HL_into, ®_hl); return reg_hl; } int V_get_base() { inline( CALL, 0xBC0B, LD_A_into, ®_a); return reg_a >> 6; } /* set screen into a new mode */ V_set_mode(mode) { reg_a = mode; inline( LD_A_from, ®_a, CALL, 0xBC0E); } /* ask the current screen mode */ int V_get_mode() { inline( CALL, 0xBC11, LD_A_into, ®_a); return reg_a; } /* clear the screen to ink 0 */ V_clear() { inline(CALL, 0xBC14); } /* ask the size of the screen in characters */ /* returns the last column (CC) and last row (RR) encoded as 0xCCRR */ int V_char_limits() { inline( CALL, 0xBC17, LD_BC_into, ®_bc); return reg_bc; } /* convert Text VDU coordinates to a screen position (and width) */ int V_char_position(row, column) { reg_hl = (column << 8) + row; inline( LD_HL_from, ®_hl, CALL, 0xBC1A, LD_HL_into, ®_hl); return reg_hl; } int V_char_width() { inline( CALL, 0xBC1A, LD_BC_into, ®_bc); return (reg_bc >> 8); } /* convert Graphics VDU coordinates to a screen position */ /* V_dot_position does as described, V_dot_aux returns mask (MM) and pixels_in_byte - 1 (PP) encoded as 0xPPMM */ int V_dot_position(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC1D, LD_HL_into, ®_hl); return reg_hl; } int V_dot_aux(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC1D, LD_BC_into, ®_bc); return reg_bc; } /* calculate the screen address to the right of the given screen address */ int V_next_byte(address) { reg_hl = address; inline( LD_HL_frTrack-Info  NABCDEFGHIom, ®_hl, CALL, 0xBC20, LD_HL_into, ®_hl); return reg_hl; } /* calculate the screen address to the left of the given screen address */ int V_prev_byte(address) { reg_hl = address; inline( LD_HL_from, ®_hl, CALL, 0xBC23, LD_HL_into, ®_hl); return reg_hl; } /* calculate the screen address below that of the given screen address */ int V_next_line(address) { reg_hl = address; inline( LD_HL_from, ®_hl, CALL, 0xBC26, LD_HL_into, ®_hl); return reg_hl; } /* calculate the screen address above that of the given screen address */ int V_prev_line(address) { reg_hl = address; inline( LD_HL_from, ®_hl, CALL, 0xBC29, LD_HL_into, ®_hl); return reg_hl; } /* encode an ink to cover all pixels in a byte */ int V_ink_encode(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBC2C, LD_A_into, ®_a); return reg_a; } /* decode an encoded ink to the appropriate ink number */ int V_ink_decode(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBC2F, LD_A_into, ®_a); return reg_a; } /* set the colours to display an ink */ V_set_ink(ink, first_colour, second_colour) { reg_a = ink; reg_bc = (first_colour << 8) + second_colour; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBC32); } /* Ask the colours an ink is currently displayed in */ /* returns first (FF) and second (SS) colour encoded thus 0xFFSS */ int V_get_ink(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBC35, LD_BC_into, ®_bc); return reg_bc; } /* set the colours to display the border in */ V_set_border(first_colour, second_colour) { reg_bc = (first_colour << 8) + second_colour; inline( LD_BC_from, ®_bc, CALL, 0xBC38); } /* Ask the colours the border is currently displayed in */ /* returns first (FF) and second (SS) colour encoded thus 0xFFSS */ int V_get_border() { inline( CALL, 0xBC3B, LD_BC_into, ®_bc); return reg_bc; } /* Set the ink flash periods (in frame flybacks) */ V_set_flashing(first_period, second_period) { reg_hl = (first_period << 8) + second_period; inline( LD_HL_from, ®_hl, CALL, 0xBC3E); } /* Ask the current ink flash periods (in frame flybacks) */ /* returns first (FF) and second (SS) periods encoded thus 0xFFSS */ int V_get_flashing() { inline( CALL, 0xBC41, LD_HL_into, ®_hl); return reg_hl; } /* Fill an area of the screen with an ink (delimited by character pos) */ V_fill_box(ink, left, right, top, bottom) { reg_a = ink; reg_de = (right << 8) + bottom; reg_hl = (left << 8) + top; inline( LD_A_from, ®_a, LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC44); } /* Fill an area of the screen with an ink (bytes) */ V_flood_box(ink, top_left_address, width_in_bytes, height_in_lines) { reg_a = ink; reg_de = (width_in_bytes << 8) + height_in_lines; reg_hl = top_left_address; inline( LD_A_from, ®_a, LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC47); } /* Swap two inks over at a character position */ V_char_invert(ink1, ink2, row, column) { reg_bc = (ink1 << 8) + ink2; reg_hl = (column << 8) + row; inline( LD_BC_from, ®_bc, LD_HL_from, ®_hl, CALL, 0xBC4A); } /* Move the whole screen up or down one character height */ /* screen_is_to_roll_up should be TRUE or FALSE as appropriate */ V_hw_roll(ink, screen_is_to_roll_up) { reg_a = ink; reg_bc = screen_is_to_roll_up ? 0xFF00 : 0 ; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBC4D); } /* Move an area of the screen up or down one character height */ /* screen_is_to_roll_up should be TRUE or FALSE as appropriate */ V_sw_roll(ink, screen_is_to_roll_up, left, right, top, bottom) { reg_a = ink; reg_bc = screen_is_to_roll_up ? 0xFF00 : 0 ; reg_de = (right << 8) + bottom; reg_hl = (left << 8) + top; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC50); } /* Expand a character matrix for the current screen mode */ V_unpack(matrix, unpack_area) { Track-Info  NABCDEFGHI reg_hl = matrix; reg_de = unpack_area; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC53); } /* Compress a character matrix to the standard form */ V_repack(ink, matrix, row, column) { reg_a = ink; reg_de = matrix; reg_hl = (column << 8) + row; inline( LD_A_from, ®_a, LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC56); } /* Set the screen write mode for the Graphics VDU */ /* pixel_write_mode is: 0 write 1 exclusive-or 2 and 3 inclusive-or */ V_access(pixel_write_mode) { reg_a = pixel_write_mode; inline( LD_A_from, ®_a, CALL, 0xBC59); } /* write some pixels to the screen ignoring the Graphics VDU write mode */ V_pixels(ink, pixel_mask, screen_address) { reg_bc = (ink << 8) + pixel_mask; reg_hl = screen_address; inline( LD_BC_from, ®_bc, LD_HL_from, ®_hl, CALL, 0xBC5C); } /* plot a purely horizontal line */ V_horizontal(ink, x_left, x_right, y) { reg_a = ink; reg_bc = x_right; reg_de = x_left; reg_hl = y; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC5F); } /* plot a purely vertical line */ V_vertical(ink, x, y_top, y_bottom) { reg_a = ink; reg_bc = y_bottom; reg_de = x; reg_hl = y_top; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBC62); } /* * * * * * E N D O F F I R M 3 * * * * * */ e, LD_HL_from, ®_hl, CALL, 0xBC62); } /* * * * * * E N D O F F I R M 3 * * /* * * * * * F I R M W A R E . L I B * * * * * */ /* */ /* F I R M 5 - Sound to Kernel */ /* Copyright (C) 1985 HiSoft */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** SOUND MANAGER INTERFACE LIBRARY **/ /* Sound Program Structure for use with SOUND_QUEUE */ typedef struct { char sp_channels; /* channel/rendezvous flags */ char sp_amp_env; /* amplitude envelope 1-15 or 0 to default */ char sp_ton_env; /* tone envelope 1-15 or 0 to default */ unsigned sp_ton_period; /* tone period 1-4095 or 0 for noise only */ char sp_noise_period; /* noise period 1-31 or 0 for tone only */ char sp_amp_initial; /* initial amplitude 0-15 */ unsigned sp_repeat_count; /* duration or envelope-repeat-count */ } sound_program; /* Channel/Rendezvous Flags */ #define sp_A_CHAN 1 /* sound on channel A */ #define sp_B_CHAN 2 /* sound on channel B */ #define sp_C_CHAN 4 /* sound on channel C */ #define sp_A_RDVZ 8 /* rendezvous with channel A */ #define sp_B_RDVZ 16 /* rendezvous with channel B */ #define sp_C_RDVZ 32 /* rendezvous with channel C */ #define sp_HOLD 64 /* hold until released */ #define sp_FLUSH 128 /* abandon all earlier sounds in queue */ /* Envelopes for Amplitude or Tone */ typedef union { struct { char ses_count; char ses_size; char ses_pause_time; } ses_software; struct { char ses_shape; unsigned ses_period; } ses_hardware; } senv_section; typedef struct { char se_count_sections; senv_section se_section[5]; } sound_envelope; /* Reset the sound Track-Info  NABCDEFGHImanager */ S_reset() { inline(CALL, 0xBCA7); } /* Add a sound to a sound queue */ /* returns TRUE (1) if sound added to queue and FALSE (0) if not because at least one queue was full */ int S_queue(sp) sound_program *sp; { reg_hl = cast(unsigned) sp; inline( LD_HL_from, ®_hl, PUSH_IX, CALL, 0xBCAA, POP_IX, LD_HL_with, 0,0, RL_L); } /* Ask if there is space on a sound queue */ /* It takes a bit coded argument (use a constant like sp_A_CHAN). returns encoded channel status as per firmware specification */ int S_check(channel_bit) { reg_a = channel_bit; inline( LD_A_from, ®_a, CALL, 0xBCAD, LD_A_into, ®_a); return reg_a; } /* Set up an event to be run when a sound queue becomes empty */ /* It takes a bit coded argument (use a constant like sp_A_CHAN). */ S_arm_event(channel_bit, eb) event_block *eb; { reg_a = channel_bit; reg_hl = eb; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBCB0); } /* Allow sounds to happen */ /* It takes a bit coded argument (use a constant like sp_A_CHAN). */ S_release(channel_bits) { reg_a = channel_bit; inline( LD_A_from, ®_a, PUSH_IX, CALL, 0xBCB3, POP_IX); } /* Stop all sounds in mid-flight */ /* returns TRUE (1) if a sound was active and FALSE (0) if not */ int S_hold() { inline( CALL, 0xBCB6, LD_HL_with, 0,0, RL_L); } /* Restart sounds after they have been held/stopped */ S_continue() { inline( PUSH_IX, CALL, 0xBCB9, POP_IX); } /* Set up an amplitude envelope */ /* This takes the envelope number 1-15 and a pointer to an envelope structure. It returns TRUE (1) if the envelope was set up OK and FALSE (0) if the envelope number was invalid */ int S_ampl_envelope(number, envelope) sound_envelope *envelope; { reg_a = number; reg_hl = envelope; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBCBC, LD_HL_with, 0,0, RL_L); } /* Set up a tone envelope */ /* as per S_ampl_envelope */ int S_tone_envelope(number, envelope) sound_envelope *envelope; { reg_a = number; reg_hl = envelope; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBCBC, LD_HL_with, 0,0, RL_L); } /* Get the address of a sound amplitude envelope */ /* returns a pointer to the envelope with the given number (just in case you had forgotten it); or NULL (0) if the number was invalid */ sound_envelope *S_a_address(number) { reg_a = number; inline( LD_A_from, ®_a, CALL, 0xBCC2, RLA, LD_A_into, ®_a, LD_HL_into,®_hl); return a_reg & 1 ? reg_hl : 0 ; } /* Get the address of a sound tone envelope */ /* returns a pointer to the envelope with the given number (just in case you had forgotten it); or NULL (0) if the number was invalid */ sound_envelope *S_t_address(number) { reg_a = number; inline( LD_A_from, ®_a, CALL, 0xBCC5, RLA, LD_A_into, ®_a, LD_HL_into,®_hl); return a_reg & 1 ? reg_hl : 0 ; } /** KERNEL INTERFACE **/ /* Event Data Types */ /* NB event blocks MUST be allocated in the central 32K of memory. (ie from 0x4000 to 0xBFFF) This will normally be the case if they are allocated as variables in a C program. */ /* struct event_block { THE ORDER (AND CONTENTS!) MAY NOT BE RIGHT !! !! !! struct event_block *ev_link; char ev_count; char ev_class; unsigned ev_routine; char ev_ROM_select; }; struct timer_block { struct timer_block *timer_link; ev_block timer_event; }; struct tick_block { struct tick_block *ticker_link; int ticker_recharge_count; int ticker_count; ev_block ticker_event; } */ /* Reset the Kernel */ /* there are several possible return values, customise the function to suit. */ E_choke_off() { inline(CALL, 0xBCC8); } /* find and initialise all background ROMs */ /* returns revised last_usable_byte. ROMs shouldn't really use low RAM, and a C program is in trouble anyway if they do! */ int E_rom_walk(first_usable_byte, last_usable_byte) { reg_de = first_usable_byte; reg_hl = last_usable_byte; inline( LD_HL_fTrack-Info  NABCDEFGHIrom, ®_hl, LD_DE_from, ®_de, CALL, 0xBCCB, LD_HL_into, ®_hl); return reg_hl; } /* initialise a particular background ROM */ /* returns revised last_usable_byte. ROMs shouldn't really use low RAM, and a C program is in trouble anyway if they do! */ E_init_back(ROM_select_address, first_usable_byte, last_usable_byte) { reg_bc = ROM_select_address; reg_de = first_usable_byte; reg_hl = last_usable_byte; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBCCE, LD_HL_into, ®_hl); return reg_hl; } /* Introduce an RSX to the firmware */ E_log_ext(command_table_address, kernel_RAM_address) { reg_bc = command_table_address; reg_hl = kernel_RAM_address; inline( LD_HL_from, ®_hl, LD_BC_from, ®_bc, CALL, 0xBCD1); } /* Search for an RSX, background ROM, or foreground ROM to process a command */ /* returns TRUE (1) if command found, and FALSE (0) otherwise. Also sets ROM_select_address and routine_address */ int E_find_command(command_name, p_ROM_select_address, p_routine_address) int *p_ROM_select_address, *p_routine_address; { reg_hl = command_name; inline( LD_HL_from, ®_hl, CALL, 0xBCD4, LD_HL_into, ®_hl, LD_BC_into, ®_bc, LD_A_with, 0, RLA, LD_A_into, ®_flags); *p_ROM_select = reg_bc & 0xFF; *p_routine_address = reg_hl; return reg_flags; } /* Initialise and put a block onto the frame flyback list */ E_new_frame_fly(frame_flyback_block, event_class, ROM_select, event_routine) { reg_hl = frame_flyback_block; reg_bc = (event_class << 8) + ROM_select; reg_de = event_routine; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBCD7); } /* Put a block onto the frame flyback list */ E_add_frame_fly(frame_flyback_block) { reg_hl = frame_flyback_block; inline( LD_HL_from, ®_hl, CALL, 0xBCDA); } /* Remove a block from the frame flyback list */ E_del_frame_fly(frame_flyback_block) { reg_hl = frame_flyback_block; inline( LD_HL_from, ®_hl, CALL, 0xBCDD); } /* Initialise and put a block onto the fast ticker list */ E_new_fast_ticker(fast_ticker_block, event_class, ROM_select, event_routine) { reg_hl = fast_ticker_block; reg_bc = (event_class << 8) + ROM_select; reg_de = event_routine; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBCE0); } /* Put a block onto the fast ticker list */ E_add_fast_ticker(fast_ticker_block) { reg_hl = fast_ticker_block; inline( LD_HL_from, ®_hl, CALL, 0xBCE3); } /* Remove a block from the fast ticker list */ E_del_fast_ticker(fast_ticker_block) { reg_hl = fast_ticker_block; inline( LD_HL_from, ®_hl, CALL, 0xBCE6); } /* put a block onto the tick list */ E_add_ticker(tick_block, initial_count, recharge_value) { reg_hl = tick_block; reg_de = initial_count; reg_bc = recharge_value; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBCE9); } /* Remove a block from the tick list */ /* returns count remaining before next event, or 257 if tick block not found */ int E_del_ticker(tick_block) { reg_hl = tick_block; inline( LD_HL_from, ®_hl, CALL, 0xBCEC, LD_DE_into, ®_de, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? reg_de : 257 ; } /* Initialise an event block */ E_init_event(event_block, event_class, ROM_select, event_routine) { reg_hl = event_block; reg_bc = (event_class << 8) + ROM_select; reg_de = event_routine; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBCEF); } /* Kick an event block */ E_event(event_block) { reg_hl = event_block; inline( LD_HL_from, ®_hl, CALL, 0xBCF2); } /* Clear synchronous event queue */ E_sync_reset() { inline(CALL, 0xBCF5); } /* Remove a synchronous event from the queue */ E_del_synchronous(event_block) { reg_hl = event_block; inline( LD_HL_from, ®_hl, CALL, 0xBCF2); } /* Get next synchronous event from queue */ /* returns the address of the event block, or NULL Track-Info  NABCDEFGHI(0) if there is none If you need the previous event priority, recover it from reg_a */ int E_next_sync() { inline( CALL, 0xBCFB, LD_HL_into, ®_hl, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? reg_hl : 0 ; } /* Perform a synchronous event routine */ E_do_sync(event_routine) { reg_hl = event_routine; inline( LD_HL_from, ®_hl, CALL, 0xBCFE); } /* Finish processing a synchronous event */ E_done_sync(previous_priority, event_block) { reg_a = previous_priority; reg_hl = event_block; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBD01); } /* Disable normal synchronous events */ E_event_disable() { inline(CALL, 0xBD04); } /* Enable normal synchronous events */ E_event_enable() { inline(CALL, 0xBD07); } /* Prevent a synchronous event from occurring */ E_disarm_event(event_block) { reg_hl = event_block; inline( LD_HL_from, ®_hl, CALL, 0xBD0A); } /* Ask the elapsed time */ E_time_please(time) int time[2]; { inline( CALL, 0xBD0D, LD_HL_into, ®_hl, LD_DE_into, ®_de); time[0] = reg_hl; time[1] = reg_de; } /* set the elapsed time */ E_time_set(time) int time[2]; { reg_hl = time[0]; reg_de = time[1]; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, CALL, 0xBD10); } /* * * * * * E N D O F F I R M 5 * * * * * */ g_hl, LD_DE_from, ®_de, CALL, 0xBD10); } /* * * * * * /* * * * * * F I R M W A R E . L I B * * * * * */ /* */ /* F I R M 2 - Text VDU to Graphics VDU */ /* Copyright (C) 1985 HiSoft */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /****** TEXT VDU INTERFACE FUNCTIONS ******/ /* Fully Initialise the Text VDU */ T_initialise() { inline(CALL, 0xBB4E); } /* Reset the Text Indirections and control code table */ T_reset() { inline(CALL, 0xBB51); } /* Allow characters to be placed on the screen */ T_vdu_enable() { inline(CALL, 0xBB54); } /* Prevent characters being placed on the screen */ T_vdu_disable() { inline(CALL, 0xBB57); } /* Output a character or control code to the text VDU */ T_output(c) { reg_a = c; inline( LD_A_from, ®_a, CALL, 0xBB5A); } /* Write a character to the screen. Control codes are printed, not obeyed */ T_wr_char(c) { reg_a = c; inline( LD_A_from, ®_a, CALL, 0xBB5D); } /* Read a character from the screen. */ /* Returns the character found or EOF (-1) if none was recognised */ int T_rd_char() { inline( CALL, 0xBB60, LD_L_A, LD_H_with, 0, JR_C, 1, DEC_HL); } /* Turn on or off the graphics VDU write character option */ /* The parameter "on" should be TRUE (1) to turn the option on and should be FALSE (0) to turn it off. */ T_set_graphic(on) { reg_a = on; inline( LD_A_from, ®_a, CALL, 0xBB63); } /* Set the size of the current text window */ T_win_enable(x1,x2,y1,y2) { reg_hl = (x1 << 8) + y1; reg_de = (x2 << 8) + y2; inline( LD_HL_from, ®_hl, LD_DE_from, ®_de, CALL, 0xBB66); } /* Get the size and position of the current window */ /* The results are put into the 4-character vector supplied as argument. edge[0] is the topmost row. edge[1] is the leftmost column number. edge[2] is the bottommost row. edge[3] is the rightmost column. The value of the function is FALSE (0) if the window covers the whole screen and TRUE (1) if it only covers part of the screen. */ int T_get_window(edge) int edge[2]; /* note the naughty type conversion */ { reg_hl = cast(unsigned) edge; inline( CALL, 0xBB69, LD_HL_into,Track-Info  NABCDEFGHI ®_hl, LD_DE_into, ®_de, LD_A_with, 0, RLA, LD_A_into, ®_flags); edge[0] = reg_hl; edge[1] = reg_hl; return reg_flags; } /* Clear current window */ T_clear_window() { inline(CALL, 0xBB6C); } /* Set cursor horizontal position */ T_set_column(x_column) { reg_a = x_column; inline( LD_A_from, ®_a, CALL, 0xBB6F); } /* Set cursor vertical position */ T_set_row(y_row) { reg_a = y_row; inline( LD_A_from, ®_a, CALL, 0xBB72); } /* Set cursor position */ T_set_cursor(x_column, y_row) { reg_hl = (x_column << 8) + y_row; inline( LD_HL_from, ®_hl, CALL, 0xBB75); } /* Ask current cursor position */ T_get_cursor(px_column, py_row, p_roll_count) int *px_column, *py_row, *p_roll_count; { inline( CALL, 0xBB78, LD_A_into, ®_a, LD_HL_into, ®_hl); *p_roll_count = reg_a; *px_column = (reg_hl >> 8) & 0xFF; *py_row = reg_hl & 0xFF; } /* Enable cursor display (may show cursor) - for normal user use */ T_cur_enable() { inline(CALL, 0xBB7B); } /* Disable cursor display (always hides cursor) - for normal user use */ T_cur_disable() { inline(CALL, 0xBB7E); } /* Turn cursor display on (may show cursor) - used by C compiler */ T_cur_on() { inline(CALL, 0xBB81); } /* Turn cursor display off (always hides cursor) - used by C compiler */ T_cur_off() { inline(CALL, 0xBB84); } /* Check if a cursor position is legal and force it to be so */ /* returns valid cursor position in x and y, POINTED AT by px_col and py_row. returns roll_count change as its result: -1 if window would roll up 0 if window would not roll +1 if window would roll down */ int T_validate(px_col, py_row) int *px_col, *py_row; { reg_hl = (*px_col << 8) + *py_row; inline( LD_HL_from, ®_hl, CALL, 0xBB87, LD_HL_into, ®_hl, LD_A_B, RLA, LD_A_into, ®_a); *px_col = (reg_hl >> 8) & 0xFF; *py_row = reg_hl & 0xFF; if ( ! reg_a) return 1; if (reg_a == 0xFE) return -1; return 0; } /* Put a cursor blob on the screen */ T_place_cursor() { inline(CALL, 0xBB8A); } /* Take a cursor blob off the screen */ T_remove_cursor() { inline(CALL, 0xBB8D); } /* Set ink for writing characters */ T_set_pen(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBB90); } /* Get ink for writing characters */ int T_get_pen() { inline( CALL, 0xBB93, LD_A_into, ®_a); return reg_a; } /* Set ink for writing text background */ T_set_paper(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBB96); } /* Get ink for writing text background */ int T_get_paper() { inline( CALL, 0xBB99, LD_A_into, ®_a); return reg_a; } /* Swap current pen and paper inks */ T_inverse() { inline(CALL, 0xBB9C); } /* Allow or disallow background being written */ /* transparent should be TRUE for transparent writing and FALSE otherwise */ T_set_back(transparent) { reg_a = transparent ? 1 : 0 ; inline( LD_A_from, ®_a, CALL, 0xBB9F); } /* Ask if background is to be written with characters */ /* returns TRUE for transparent writing and FALSE otherwise */ int T_get_back() { inline( CALL, 0xBBA2, LD_A_into, ®_a); return reg_a ? 1 : 0 ; } /* Get the address of a character matrix */ /* If the address is in the range 0000 - 0x3FFF then the matrix is in the lower ROM, and otherwise its in RAM. (The program occupies low RAM). */ int T_get_matrix(character_number) { reg_a = character_number; inline( LD_A_from, ®_a, CALL, 0xBBA5, LD_HL_into, ®_hl); return reg_hl; } /* Set the contents of a character matrix */ /* returns TRUE (1) if all OK, and FALSE if character is not user definable */ T_set_matrix(character_number, matrix_address) { reg_a = character_number; reg_hl = matrix_address; inline( LD_A_from, ®_a, LD_HL_from, ®_hl, CALL, 0xBBA8, LD_A_with, 0, RLA, LD_A_into, ®_a); return reg_a; } /* Set the user defined matrix table address */ T_set_m_table(first_character, table_address) { reg_de = first_character; reg_hl = table_address; Track-Info  NABCDEFGHI inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBAB); } /* Get user defined matrix table address */ /* This function just returns the address (or NULL (0) if there is none). Use the next function "T_get_mchar" to find the first character in it. */ int T_get_m_table() /* get address of table */ { inline( CALL, 0xBBAE, LD_HL_into, ®_hl, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? reg_hl : 0 ; } int T_get_mchar() /* get first character in table */ { inline( CALL, 0xBBAE, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? reg_a : 0 ; } /* Fetch address of control code table */ int T_get_controls() { inline( CALL, 0xBBB1, LD_HL_into, ®_hl); return reg_hl; } /* Select a Text VDU stream */ /* returns the previously selected stream number */ int T_str_select(stream_number) { reg_a = stream_number; inline( LD_A_from, ®_a, CALL, 0xBBB4, LD_A_into, ®_a); return reg_a; } /* Swap the states of two streams */ T_swap_streams(stream_number, another_stream_number) { reg_bc = (stream_number << 8) + another_stream_number; inline( LD_BC_from, ®_bc, CALL, 0xBBB7); } /** GRAPHIC VDU INTERFACE FUNCTIONS **/ /* fully initialise the graphics vdu */ G_initialise() { inline(CALL, 0xBBBA); } /* reset the graphics vdu indirections to their default */ G_reset() { inline(CALL, 0xBBBD); } /* move to an absolute graphics position */ G_move_absolute(x,y) { reg_de = x; reg_hl = y; inline(LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBC0); } /* move relative to current graphics position */ G_move_relative(dx, dy) { reg_de = dx; reg_hl = dy; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBC3); } /* get the current graphics position */ G_ask_cursor(pdx, pdy) int *pdx, *pdy; { inline( CALL, 0xBBC6, LD_DE_into, ®_de, LD_HL_into, ®_hl); *pdx = reg_de; *pdy = reg_hl; } /* set the origin of the user coordinates */ G_set_origin(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBC9); } /* get the origin of the user coordinates */ G_get_origin(pdx, pdy) int *pdx, *pdy; { inline( CALL, 0xBBCC, LD_DE_into, ®_de, LD_HL_into, ®_hl); *pdx = reg_de; *pdy = reg_hl; } /* set the left and right edges of the graphics window */ G_win_width(x1, x2) { reg_de = x1; reg_hl = x2; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBCF); } /* set the top and bottom edges of the graphics window */ G_win_height(y1, y2) { reg_de = y1; reg_hl = y2; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBD2); } /* get the left and right edges of the graphics window */ G_get_width(px1, px2) int *px1, *px2; { inline( CALL, 0xBBD5, LD_DE_into, ®_de, LD_HL_into, ®_hl); *px1 = reg_de; *px2 = reg_hl; } /* get the top and bottom edges of the graphics window */ G_get_height(py1, py2) int *py1, *py2; { inline( CALL, 0xBBD8, LD_DE_into, ®_de, LD_HL_into, ®_hl); *py1 = reg_de; *py2 = reg_hl; } /* clear the graphics window */ G_clear_window() { inline(CALL,0xBBDB); } /* set the graphics plotting ink */ G_set_pen(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBBDE); } /* get the graphics plotting ink */ int G_get_pen() { inline( CALL, 0xBBE1, LD_L_A, LD_H_with, 0); } /* set the graphics background ink */ G_set_paper(ink) { reg_a = ink; inline( LD_A_from, ®_a, CALL, 0xBBE4); } /* get the current graphics background ink */ int G_get_paper() { inline( CALL, 0xBBE7, LD_L_A, LD_H_with, 0); } /* plot a point at an absolute position */ G_plot_absolute(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBEA); } /* plot a point relative to the current position */ G_plot_relative(dx, dy) { reg_de = dx; reg_hl = dy; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBED); } /* test which ink is at aTrack-Info  NABCDEFGHIn absolute position */ int G_test_absolute(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBF0, LD_L_A, LD_H_with, 0); } /* test which ink is at a position relative to the current one */ int G_test_relative(dx, dy) { reg_de = dx; reg_hl = dy; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBF3, LD_L_A, LD_H_with, 0); } /* draw a line to an absolute position */ G_line_absolute(x, y) { reg_de = x; reg_hl = y; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBF6); } /* draw a line relative to the current position */ G_line_relative(dx, dy) { reg_de = dx; reg_hl = dy; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBBF9); } /* plot a character on the screen at the current graphics position */ G_wr_char(c) { reg_a = c; inline( LD_A_from, ®_a, CALL, 0xBBFC); } /* * * * * * E N D O F F I R M 2 * * * * * */ c; inline( LD_A_from, ®_a, CALL, 0xBBFC); } /* * * *}l#͔.͒/*Tk*Tl"}2"}2*/ī0͊/0da=*R(sPN:(($(( (,sPy((6#=Oɹyy 6ɹ #^#V*'TR !":*( ( (>~ : ͥN"͍0[T*!TR8sP!ST*ͫ.͗0*#^#VM1*'T"*#~#fo"'Tͤ.: x}(:  a=*RsP:!(! (( ͗0*#^#V*)UR")U"/* * * * * * F I R M W A R E . L I B * * * * * */ /* */ /* F I R M 6 - Machine Pack */ /* Copyright (C) 1985 HiSoft */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** MACHINE PACK INTERFACE FUNCTIONS **/ /* Load and run a program */ M_boot_program(loader) { reg_hl = loader; inline( LD_HL_from, ®_hl, CALL, 0xBD13); } /* run a program */ M_start_program(entry_address, ROM_select) { reg_hl = entry_address; reg_bc = ROM_select; inline( LD_HL_from, ®_hl, LD_BC_from, ®_bc, CALL, 0xBD16); } /* wait until frame flyback is detected (and this condition persists) */ M_wait_flyback() { inline(CALL, 0xBD19); } /* set the screen mode */ M_set_mode(mode) { reg_a = mode; inline( LD_A_from, ®_a, CALL, 0xBD1C); } /* set screen offset */ M_screen_offset(base, offset) { reg_a = base; reg_hl = offset; inline( LD_HL_from, ®_hl, LD_A_from, ®_a, CALL, 0xBD1F); } /* set all inks to one colour */ /* the parameter is the address of the border colour (BB) and ink colour (II) encoded as 0xIIBB. */ M_clear_inks(ink_vector) { reg_de = ink_vector; inline( LD_DE_from, ®_de, CALL, 0xBD22); } /* set colours of all inks */ M_set_inks(ink_vector) { reg_de = ink_vector; inline( LD_DE_from, ®_de, CALL, 0xBD25); } /* reset the printer indirection */ M_reset_printer() { inline(CALL, 0xBD28); } /* try to send a character to the Centronics port */ /* NB the time-out is too short (in particular for a DMP1) and the printer will appear to time out when a newline is sent returns the character or EOF (-1) if it timed out */ int M_print_char(character) { reg_a = character; inline( LD_A_from, ®_a, CALL, 0xBD2B, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags ? reg_a : -1 ; } /* test if the Centronics port is busy */ /* returns TRUE (1) if busy and FALSE (0) if not */ int M_busy_printer() { inline( CALL, 0xBD2E, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags; } /* send a character to the Centronics port */ M_send_printer(character) { reg_a = character; inline( LD_A_from, ®_a, CALL, 0xBD31); } /* send data to a sound chip register */ M_sound_register(sound_chip_register, data) { reg_a = sound_chip_register; reg_bc = data; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBD34); } /** RESTORE THE STANDARD JUMPBLOCKS */ Jump_restore() { inline(CALL, 0xBD37); } /* * * * * * E N D O F F I R M 6 * * * * * */ BLOCKS Track-Info  NABCDEFGHI/* * * * * * F I R M W A R E . L I B * * * * * */ /* */ /* F I R M 1 - Keyboard to Graphics VDU */ /* Copyright (C) 1985 HiSoft */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This library file provides a simple interface to each of the firmware routines accessed through the jumpblocks in Amstrad computers. Many of the functions are already provided in one way or another in the standard C library and they should always be used in preference for the sake of portability and ease of understanding (eg use getchar() or rawin() in preference to T_wait_char()). BASIC.LIB also contains some easier-to-use functions which can also be used. The functions are listed in the same order as in the Firmware Specification and you should refer to it for further details of what the functions do. The names of the functions have been kept as close as possible to the corresponding jumpblock entry name. The major difference is that the prefix for most groups of functions has been turned into a single character (because C identifiers must differ in the first eight places). The group prefixes are K KM Key Manager T TXT Text VDU G GRA Graphics VDU V SCR Screen Pack C CAS Cassette Manager S SOUND Sound Manager E KL Kernel M MC Machine Pack */ /* /** Z80 Definitions for Functions Using Locomotive Firmware **/ /* Z80 instruction set definitions */ #define LD_A_from 0x3A #define LD_HL_from 0x2A #define LD_BC_from 0x4BED #define LD_DE_from 0x5BED #define LD_HL_into 0x22 #define LD_A_into 0x32 #define LD_BC_into 0x43ED #define LD_DE_into 0x53ED #define LD_HL_with 0x21 #define LD_H_with 0x26 #define LD_A_with 0x3E #define RLA 0x17 #define INC_HL 0x23 #define JR_Z 0x28 #define DEC_HL 0x2B #define JR_C 0x38 #define INC_A 0x3C #define LD_L_A 0x6F #define LD_A_B 0x78 #define ADD_A_C 0x81 #define CALL 0xCD #define RL_L 0x15CB #define POP_IX 0xDDE1 #define PUSH_IX 0xDDE5 /* Z80 register interface variables */ unsigned reg_bc, reg_de, reg_hl; char reg_a, reg_flags; /****** KEY MANAGER INTERFACE FUNCTIONS ******/ /* Fully Initialise the Key Manager */ K_initialise() { inline(CALL, 0xBB00); } /* Reset the Key Manager Indirections and Buffers */ K_reset() { inline(CALL, 0xBB03); } /* Wait for the next character from the keyboard */ int K_wait_char() { inline( CALL, 0xBB06, LD_A_into, ®_a); return reg_a; } /* Test if a character is available from the keyboard */ /* returns -1 (EOF) if there is no character available, and the character value if there is */ int K_read_char() { inline( CALL, 0xBB09, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); if (reg_flags) return reg_a; return -1; } /* Return a single character to the keyboard for next time */ K_char_return(c) { reg_a = c; inline( LD_A_from, ®_a, CALL, 0xBB0C); } /* Set an expansion string */ K_set_expand(expansion_token, string_length, string) { reg_bc = (expansion_token << 8) + string_length; reg_hl = string; inline( LD_BC_from, ®_bc, LD_HL_from, ®_hl, CALL, 0xBB0F); } /* Get a character from an expansion string */ /* returns -1 (EOF) if there is no character available, and the character value if there is */ int K_get_expand(expansion_token, character_number) { reg_a = expansion_token; reg_hl = character_number; inline( LD_A_from, ®_a, LD_HL_from,®_hl, CALL, 0xBB12, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); if (reg_flags) return reg_a; return -1; } /* Allocate a buffer for expansion strings */ /* returns TRUE (1) if everything OK and FALSE (0) if buffer too short */ K_exp_buffer(address_of_buffer, length_of_buffer) { reg_de = address_of_buffer; reg_hl = length_of_buffer; inline( LD_DE_from, ®_de, LD_HL_from, ®_hl, CALL, 0xBB15, LD_A_with, 0, RLA, LD_A_into, ®_flags); return reg_flags; } /* Wait for a key to Track-Info  NABCDEFGHIbe pressed */ int K_wait_key() { inline( CALL, 0xBB18, LD_A_into, ®_a); return reg_a; } /* Test if a key has been pressed */ /* returns -1 (EOF) if there is no character available, and the character value if there is */ int K_read_key() { inline( CALL, 0xBB1B, LD_A_into, ®_a, LD_A_with, 0, RLA, LD_A_into, ®_flags); if (reg_flags) return reg_a; return -1; } /* Test if a key is pressed */ /* returns a bit-significant value: bit mask meaning_if_set 0 1 the key is pressed 5 32 a shift key is pressed 7 128 the control key is pressed */ int K_test_key(key_number) { reg_a = key_number; inline( LD_A_from, ®_a, CALL, 0xBB1E, LD_A_with, 0, JR_Z, 1, INC_A, ADD_A_C, LD_A_into, ®_a); return reg_a & (128+32+1) ; } /* Fetch Caps Lock and Shift Lock states */ /* returns 0xFFFF if both Caps Lock and Shift Lock are on; and 0xFF00 if just Caps Lock is on; and 0x00FF if just Shift Lock is on; and 0x0000 if neither is on. */ int K_get_state() { inline( CALL, 0xBB21, LD_HL_into, ®_hl); return reg_hl; } /* Fetch current state of joystick */ /* returns state of both joysticks, encoded in an int: 0xAABB (AA is state of joystick a, BB that of joystick b */ int K_get_joystick() { inline( CALL, 0xBB24, LD_HL_into, ®_hl); return reg_hl; } /* Set entry in key translation table without shift or control */ K_set_translate(key_number, translation) { reg_a = key_number; reg_bc = translation << 8; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBB27); } /* Get entry from key translation table without shift or control */ int K_get_translate(key_number) { reg_a = key_number; inline( LD_A_from, ®_a, CALL, 0xBB2A, LD_A_into, ®_a); return reg_a; } /* Set entry in key translation table when shift key is pressed */ K_set_shift(key_number, translation) { reg_a = key_number; reg_bc = translation << 8; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBB2D); } /* Get entry from key translation table when shift key is pressed */ int K_get_shift(key_number) { reg_a = key_number; inline( LD_A_from, ®_a, CALL, 0xBB30, LD_A_into, ®_a); return reg_a; } /* Set entry in key translation table when control key is pressed */ K_set_control(key_number, translation) { reg_a = key_number; reg_bc = translation << 8; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBB33); } /* Get entry from key translation table when control key is pressed */ int K_get_control(key_number) { reg_a = key_number; inline( LD_A_from, ®_a, CALL, 0xBB36, LD_A_into, ®_a); return reg_a; } /* Set whether a key may repeat */ /* Set repeat TRUE (1) to allow repeat, and FALSE (0) to prevent it. */ K_set_repeat(key_number, repeat) { reg_a = key_number; reg_bc = repeat ? 0xFF00 : 0 ; inline( LD_A_from, ®_a, LD_BC_from, ®_bc, CALL, 0xBB39); } /* Ask if a key is allowed to repeat */ /* Returns TRUE (1) if key is allowed to repeat, and FALSE (0) if not */ int K_get_repeat(key_number) { reg_a = key_number; inline( LD_A_from, ®_a, CALL, 0xBB3C, LD_A_with, 0, JR_Z, 1, INC_A, LD_A_into, ®_a); return reg_a; } /* Set repeat speed and start up delay */ K_set_delay(start_up_delay, repeat_speed) { reg_hl = (start_up_delay << 8) + repeat_speed; inline( LD_HL_from, ®_hl, CALL, 0xBB3F); } /* Get repeat speed and start up delay */ /* returns delay (dd) and speed (ss) encoded as 0xddss */ int K_get_delay() { inline( CALL, 0xBB42, LD_HL_into, ®_hl); return reg_hl; } /* Allow break events to be generated */ K_arm_breaks(event_routine, ROM_select) { reg_de = event_routine; reg_bc = ROM_select; inline( LD_DE_from, ®_de, LD_BC_from, ®_bc, CALL, 0xBB45); } /* Prevent break events from being generated */ K_disarm_break() { inline(CALL, 0xBB48); } /* Generate a break event (if armed) */ K_break_event() { inline(CALL, 0xBB4B); Track-Info  N A B C D E F G H I} /* * * * * * E N D O F F I R M 1 * * * * * */ d) */ K_break_event() { inline(CALL, 0xBB4B); V>2+U-$&{ ͮ2>2+U2}V.*)U|( %O!!A!>ROt&$&} 42}V<2+U2H$&{ T{ }  Hy 2$&>2 Vy*>V-$&,(&*(T!+.) C.~*Q[Q (' R8`i>O*QR9.( ~ [Q^#VØ. [Qs#rð.[Q2C^#V"9.("*TR(  *TR8Track-Info ! N!A!B!C!D!E!F!G!H!ITrack-Info " N"A"B"C"D"E"F"G"H"ITrack-Info # N#A#B#C#D#E#F#G#H#ITrack-Info $ N$A$B$C$D$E$F$G$H$ITrack-Info % N%A%B%C%D%E%F%G%H%ITrack-Info & N&A&B&C&D&E&F&G&H&ITrack-Info ' N'A'B'C'D'E'F'G'H'I