Jump to content



- - - - -

Bulls And Cows


  • Please log in to reply
41 replies to this topic

#1 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 01 January 2006 - 03:32 PM

dear afx programmers! please help me with porting this code:

const MaxSgn = 6; 
Sgn = 4; 
type S = 1..MaxSgn;
Numb = array[1..Sgn] of S;
function cows(n1,n2:Numb):byte;
var i1,i2 : 1..Sgn;
a : byte;
begin
a:=0;
for i1:=1 to Sgn do
for i2:=1 to Sgn do
if n1[i1]=n2[i2] then
if i1=i2 then a:=a+10 
else inc(a);
cows:=a;
end;
type Step = Record 
n : Numb; 
answer : byte; 
end;
Game = array[1..32] of step;
var Nstep : byte; 
Info : Game;
Curnumb : Numb; i,j : integer; b : boolean;
BEGIN
clrscr;
for i:=1 to Sgn do Curnumb[i]:=i;
Nstep:=0;
while true do
begin
for i:=1 to Sgn do write(Curnumb[i]);
write(' ? ');
inc(Nstep);
Info[Nstep].n:=Curnumb;
readln(Info[Nstep].Answer);
if (Info[Nstep].Answer div 10+Info[Nstep].Answer mod 10)>Sgn then
begin writeln('bad game !'); exit; end;
if Info[Nstep].Answer=10*Sgn then exit;
repeat
i:=Sgn;
while (i>=1) and (Curnumb[i]=MaxSgn) do
begin
Curnumb[i]:=1;
dec(i);
end;
if i<1 then
begin 
writeln('your answers in not right !'); exit; end;
inc(Curnumb[i]);
b:=true;
for i:=1 to Sgn do
for j:=i+1 to Sgn do
b:=b and (Curnumb[i]<>Curnumb[j]);
for i:=1 to Nstep 
   do b:=b and (cows(Curnumb,Info[i].n)=Info[i].Answer);
until b;
end;
END.

questions:
1. i don't know how to input answers (readln not worked, therefore need to read keycodes etc...)
2. what libraries i must use if programming in turbo pascal 60? AFXTP 1.0 is not really documented, and its functions is not enough:(
3. how change program if i want to define "Sgn" in a worked program dynamically, not as a constant?
4. how to draw a buttons like in original casio addons? and how to use them, for example, to start a program from beginning or stop program execution?
5. is there any guides about programminf for afx in turbo pascal?

if you can, please put in this topic a worked variant of the program for afx

thanks

#2 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 04 January 2006 - 09:57 PM

I'm found a solution for input answers:) Oh, sorry! I forgot to tell that Bulls and Cows is a russian analog of MasterMind game, but this is no colors, there are digits. and cow mean that digit exist in number, bull mean that it's exist and in right place. sorry for my bad english:)
so can anyone help me with writing some short procedures in assembler to use they in my program? I wrote they in pascal but this is not optimal for speed. and I don't know how to use the inline assembler:(
also I need to know how to process interrupts if I intercept them (for example for keyboard reaction in program in any moment). can anyone help me?
I can put my sources here if needed. however, they are far from optimal because I'm not an advanced programmer. programming is only my hobby.

#3 Orwell

Orwell

    Casio Overlord

  • Members
  • PipPipPipPipPipPipPip
  • 777 posts
  • Gender:Male
  • Location:Paris - France

  • Calculators:
    Casio AFX 1.02 / Casio ClassPad 300

Posted 05 January 2006 - 12:55 PM

so can anyone help me with writing some short procedures in assembler to use they in my program? I wrote they in pascal but this is not optimal for speed. and I don't know how to use the inline assembler:(

But do you really need some speed optimisation for a mastermind game? :blink: I think pascal should be more fast than enough :huh:

also I need to know how to process interrupts if I intercept them

Marco should certainly know how to do that in pascal... He will surely answer himself :)

#4 Marco

Marco

    Casio Freak

  • Members
  • PipPipPipPip
  • 185 posts
  • Location:Dresden, Germany

  • Calculators:
    Casio CFX 9850G (broken),
    Casio CFX 9850GB,
    Casio Algebra FX 2.0 Plus

Posted 06 January 2006 - 06:22 PM

Fine, a new Pascal coder for AFX :)

2. what libraries i must use if programming in turbo pascal 60? AFXTP 1.0 is not really documented, and its functions is not enough:(

Yeah, it's not really documented (I considered the the variable's and function's names as self explaining and also was too lazy to write a doc, sorry). But functions should be enough. There are different units implementing most stuff needed (e.g. AFXCRT implementing CRT functions, AFXSTDIO implementing standard I/O = readln/writeln, AFXGFX graphic routines, AFXTIME implementing timer support and so on).

First, for your bulls and cows - program, just unsert "uses afxcrt,afxstdio" as the first line. AFXCRT gives you the standard CRT functions "gotoxy", "clrscr" and so on as you know them from unit CRT (PC, DOS). And AFXSTDIO (implementing a wrapper) will establish standard in - and output variables automatically so you can use READLN and WRITELN commands in your program.

Then, after BEGIN of the main program (before the clrscr - command), call SETCRTMODE function. This will setup text mode, clear the screen and initialise various variables of AFXCRT - unit (it's needed to call SETCRTMODE once before using an AFXCRT - function).

That's it, your program should work fine then.

3. how change program if i want to define "Sgn" in a worked program dynamically, not as a constant?

As for SGN: just make it a variable if you want it's contents changing during runtime (Be aware that you need to change the line Numb = array[1..Sgn] of S; to Numb = array[1..MaxSgn] of S; then, and of course var i1,i2 : 1..Sgn; to var i1,i2 : 1..MaxSgn;, too). Then you can assign any values from 1 to MaxSgn to Sgn.

4. how to draw a buttons like in original casio addons? and how to use them, for example, to start a program from beginning or stop program execution?

If you want to draw buttons, you can use AFXGFX unit. On startup, just call SETGFXMODE(MODE_BW) for initializing BW, and SETGFXMODE(MODE_GREY) for grey scale mode. Then you can use all the functions like SETPIXEL, VLINE, HLINE, RECTANGLE, LINE, MOVETO, LINETO, FILLCIRCLE et.c. (I think this functions really are self explaining), there are also some more complex functions like drawing bitmaps na dpage flipping.

5. is there any guides about programminf for afx in turbo pascal?

Well, none that is especially for pascal, but it works in pascal the same way as for any other language. I'd advise you to read Oliver Coupelons's Programming Guide (see algebrafx2.earthforge.com).

so can anyone help me with writing some short procedures in assembler to use they in my program? I wrote they in pascal but this is not optimal for speed. and I don't know how to use the inline assembler:(

As Orwell said, you really don't need it, not for that kind of game at least. Pascal is fast enough, cause the AFX' CPU executes the compiled program directly (not like the the Casio Basic Programs). Even if you'd rewrite the program completely in ASM, you'll not notice _any_ difference in speed. In general, only very computing intensive routines (e.g. graphic routines, see AFXGFX source) or hardware stuff should be written in ASM, the whole rest in a High Level Language (--> even very complex games are written in C or Pascal, not Assembler).

But if you want to use inline assembler in spite of, you can do it with that like statements in Turbo Pascal:

asm
  mov ax,123
  ...
end;

also I need to know how to process interrupts if I intercept them

If you use unit AFXSYS in your program, you can access the interrupt vectors directly by INTVECTS arrays. If you want to install an own interrupt handler (e.g. timer interrupt $1C), store the old value of INTVECTS[$1C] to restore it later, then write the adress of your handler (wich must be an interrupt procedure) to INTVECTS[$1C].

procedure myhandler; interrupt;
begin
  ...
end;

var oldhandler: pointer;

begin
  oldhandler := intvects[$1C];
  intvects[$1C] := myhandler;
  ...

  intvects[$1C] := oldhandler;
end.
That's it. What the MYHANDLER procedure does is upon yours then.

#5 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 06 January 2006 - 10:39 PM

thank you all fo replies:)
sorry, I forgot to tell that this is more solver than game:)) Bulls and Cows is a very popular game on the lectures in our university. but my friend wins too often <_< so I decide to make this little helper fo me ;)
but this is no problem to add a game mode because the part when a calc thinks a number and a man guess it is much more simple than if a man thinks and calc guess... so, when I understand how to implement a current part, I will add a game mode and then upload to filesharing. with a full source, of course.

I have a little more questions to Marco:
1. does readln procedure works if I use afxcrt? I try it but my can't confirm my input (try to press exe after). maybe it's not worked because I don't use SETCRTMODE? or I need to use afxstdio module? or both?
edited: already found a solution: use afxcrt and call setcrtmode:
2. if readln would work, then if I replace an interrupt 9h with my procedure, will readln and other functions from your modules can work? does they use int 9h for work or not? and if they use, how to implement an interrupt handler with that this functions would work? or how to realize for example readln, writeln, gotoxy and other without your modules?
I need to intercept int 9h because I need to react on esc key in any moment! for example, to terminate a calculation.
edited: readln won't work when I replace an int 9h:( what I need to do for working readln and keypressed? or how to pass a processing to an old interrupt without restoring it? in my handler I only examine the esc, up and down keys only. how to call old interrupt to process other keys?
3. if I draw a buttons how draw an output text in the program? It will replace the buttons, isn't it?
and how implement a scroll of outputted text (if i want to scroll up with up key, and down with down key)? please write an exaple (need some buffer i suggest).
4. really need some speed optimisations. do you know a fast algoritm that prints a rearrangements without repeats from n by m? for example for n=3 and m=3 there are:
123 132 213 231 312 321
I need to generate a numbers in some range (and in array by digits), that doesnt have repeated digits.
I found some kind of this algorithm but it is slow! for exaple, generation of 6-digit number with digits from 1 to 9 will waste ~70sec.
5. now my sources are completely different than those I post there some days ago. I can send to you my current sources or post its there if needed. my sources is very far from optimal:( can you help me in optimizing they?
6. I read on your site that you planned to release AFXTP 2.0
do you made it? or when you can finish it? I think that next version+documentation will be very useful for an afx pascal coders:)

and finally, Casio AFX - rulezzz! never seen before a calc with x86 compatible proc and DOS operating system :o some days ago I'm and my friend was maked a cable for my AFX2.0, so I decide to try to program for it B)

uffff. my native language is russian, so write so many on english is a hard task for me...

Edited by feanor, 07 January 2006 - 12:56 AM.


#6 Marco

Marco

    Casio Freak

  • Members
  • PipPipPipPip
  • 185 posts
  • Location:Dresden, Germany

  • Calculators:
    Casio CFX 9850G (broken),
    Casio CFX 9850GB,
    Casio Algebra FX 2.0 Plus

Posted 07 January 2006 - 04:11 PM

1)

You must use both, AFXCRT and AFXSTDIO, and then call SETCRTMODE. Because AFXSTDIO wraps standard I/O variables into AFXCRT functions. If you don't use AFXSTDIO, READLN / WRITELN will assume a 80x25 screen (--> no line break and no scrolling on AFX screen), and readln will not work proper because AFX uses other keycodes then PC. E.g., EXE <> #13 on AFX, thus you can't confirm your input by pressing EXE if not using AFXSTDIO.

2)

The other functions work, but keyboard related (such as READLN, KEYPRESSED and READYKEY) not because they use DOS keyboard buffer which is filled by Int 9.

If you need to intercept keyboard interrupts but want to DOS to listen to Int 9 further on, make your own keyboard handler which checks for ESC key and then calls the original DOS handler. Note that the DOS handler routine will return by IRET instruction (--> it's an interrupt routine), so you must not call it, but jump to it as the last instruction of your handler routine. Also ensure that stack is left clear. You need assembler to do this, so I'd advise to use an assembler wrapper routine which first calls your handler written in Pascal and then jumps to the DOS handler. I'd never try that before, but should work this way.

var doshandler: pointer;

{your handler routine; return TRUE if you want the DOS handler called afterwards,}
{else FALSE. E.g., return FALSE if ESC was pressed so that DOS doesn't process it again.}

function myhandler: boolean;
begin
  ...
end;

procedure wrapper; interrupt; assembler;
asm
  call myhandler
  cmp al,0
  jz @m1

  jmp far doshandler
  @m1:
end;

begin
  doshandler := intvects[9];
  intvects[9] := wrapper;
  ...
  intvects[9] := doshandler;
end.

3)

AFXGFX doesn't implement text output. You can easily implement it yourself though by making a bitmap for each char. Then write a DRAWSTRING routine which goes through the chars of the string DRAWCHAR wich draws the corresponding bitmap.

4)

Maybe one could optimize the algorithm, but it's no wonder that it takes so long, because you have very much arrangements for m=6 digits from 1 to n=9, namely 9!/(9-6)! = 60480. Why do you want to store them all in an array :blink:?

That wastes much memory (AFX can't store 60480 x 6 digits at all) and is slow. And remember, even greater m and n could occour.

In stead of generating the whole array, you should implement a function which computes just rearrangement number i. Whenever you need an element of the array (element with index i), use the rearrangement function instead of. That's much faster and needs much less memory. Indeed accessing one rearrangement is slower then, but it's fast enough that you don't notice it (because the function should be able to generate around 1000 rearrangements a second if you need 70 seconds to generate 60480).

I would implement it this like:

mmax = 16;
type trange = array[0..mmax-1];

var r: trange;

function generate_range_i(m,n: byte; i: longint);
var cur: longint;  
	digs: array[0..9] of byte;
begin
  for cur := 0 to 9 do digs[cur] := cur;

  for m := m-1 downto 0 do
  begin
	cur := i mod n;
	i := i div n;

	r[m] := digs[cur];
	if cur < n-1 then move(digs[cur+1],digs[cur],n-cur);
	dec(n);
  end;
end;

begin
end.
where m is the number of digits, mmax the maximum number of digits and i is in the range from 0 (for the first arrangement) to n!/(n-m)!-1 (for the last arrangement in the order). The arrangement is assigned to variable r. NOT TESTED!!! But the algorithm should be fine at least. It takes out the i0 th of n digits, then the i1 th out of (n-1) digits not taken yet, then the i2 th out of (n-2) and so on, and does so m times. Wich one will be taken is encoded in i (--> i = i0+i1*n+i2*n*(n-1)+...).

5)

Sorry, no, that's too much work. I'm always up for answering your questions, but I'll not optimize your complete programs. Except ... you pay for it! :r-t-f-m: :greengrin:

6)

Well, I stopped all my AFX projects ca. 8 months ago, so AFXTP 2.0 and all that stuff never got finished. However, some of the modules were far in progress yet when I stopped, so I could give the sources if you want, maybe they were usefull for you (you also may modify or continue developing them)

#7 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 07 January 2006 - 07:17 PM

Marco, your code doesn't work:(
I try yo test this short program:
(I modified a far jump to call)
uses afxcrt,afxstdio,afxsys;

var old_int9:pointer;

procedure kbd_handler; interrupt; assembler;
asm
 pushf
 call old_int9
end;

var a,b:string;

begin
 setcrtmode;
 clrscr;
 write('type something:');
 readln(b);
 writeln;
 writeln(b);
 old_int9:=intvects[9];
 intvects[9]:=@kbd_handler;
 write('type something:');
 readln(a);
 writeln;
 writeln(a);
 intvects[9]:=old_int9;
end.
but in 2nd input 8 are always printed, one if anykey pressed and one if released. on any key printed characters not differ, only 88 and so on.
if I use your method (far jmp), my program stop an execution after the second input (when I replaced interrupt handler)
so, I dosn't understood how to call an original interruption from my handler.
somewhere in the internet I've read this example:
var SvInt09 : procedure;
SvExitProc : pointer;
IsBIOSActive: boolean;
KeyPressed : array[0..255] of boolean;
CurKey : byte; 
procedure ProcessKeyb;
 const PrevKey: byte=0;
 var key,IsGray: byte;
begin
 key:=Port[$60];
 if PrevKey=224 then IsGray:=$80 else IsGray:=0;
 if key<>224 then begin 
  if key>127 then KeyPressed[key-128+IsGray]:=false
   else KeyPressed[key+IsGray]:=true;
 end;
 if key<128 then CurKey:=key;
 PrevKey:=key;
end;

procedure NewInt09; interrupt;
begin
 ProcessKeyb;
 if IsBIOSActive then begin Inline($9C); SvInt09 end;
  else Port[$20]:=$20;
end; 

procedure CloseKeyboard; forward;

procedure OpenKeyboard(LockBIOS: boolean);
begin
 FillChar(KeyPressed,256,0);
 CurKey:=0;
 GetIntVec(9,@SvInt09);
 SetIntVec(9,@NewInt09);
 IsBIOSActive:=not LockBIOS;
 SvExitProc:=ExitProc;
 ExitProc:=@CloseKeyboard;
end; 

procedure CloseKeyboard;
begin
 if @SvInt09=nil then Exit;
 SetIntVec(9,@SvInt09);
 @SvInt09:=nil;
 ExitProc:=SvExitProc;
end;
but. if I try to test it in ms-dos subsystem in windows98 with pcxxx.tpu libraries - it works ok. but if I use afxxxx.tpu and emulator or real calculator - again I have only repeated digit at all.
what does this mean? I think when we calling original interruption, it doesn't get all required parameters to work. so, how to do this? what do you think?

and what about sources... yes! they will be useful for me. if you can, please send me at xxakep(at)inbox.ru

#8 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 07 January 2006 - 07:46 PM

I don't know much about pointers in Turbo Pascal but make sure that the pointer type is a Far Pointer (look in the docs of TP) cause if not then you get problems because the calc assumes the Int 9h Offset to be in you programs segment what it ouf course is not! You really need to save segment & Register!

#9 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 07 January 2006 - 07:53 PM

huhn_m, please write an example in assembler, how to save registers and segment, and how to call original interrupt. I don't know asm at all, so its very hard to understand what you tell :)

#10 Marco

Marco

    Casio Freak

  • Members
  • PipPipPipPip
  • 185 posts
  • Location:Dresden, Germany

  • Calculators:
    Casio CFX 9850G (broken),
    Casio CFX 9850GB,
    Casio Algebra FX 2.0 Plus

Posted 07 January 2006 - 11:50 PM

Well, if you use JMP FAR instead of CALL FAR, you mustn't use PUSHF then because you have just one IRET (that of the DOS handler wich will never return to your handler, but directly to the original return adress). Both ways, PUSHF + CALL FAR and JMP FAR without PUSHF, should work fine.

!!!Either PUSHF + CALL FAR, or JMP FAR without PUSHF!!!

If PUSHF + CALL FAR does not work proper as in your case (note: the compiler should make the call a call far by by itself as it sees a pointer is 32 bit, nevertheless try CALL FAR instead of CALL), maybe it's because int 9 is not the original keyboard IRQ on AFX, but called by another wrapper interrupt (wich is the original keyboard IRQ) and leaving parameters on the stack for int 9.

In that case, you may NOT modify the stack in any way for the DOS handler (--> you may push something, but pop it before entering the DOS handler routine), thus use the JMP FAR method instead of PUSHF + CALL FAR.

Would be the same reason then why the code you got from the internet does not work, cause it's equivalent to PUSHF+CALL FAR - method. Besides, you can't use it for AFX as the code is for PC. For example, Port[$20]:=$20 tells the interrupt controller on PC that a hardware interrupt has been processed and next one can come. On AFX however, this has no effect and also the keyboard ports have other adresses.

An alternative method you could try if nothing else works, shift the DOS handler to another unused interrupt (e.g. INT $40 or something), install yours to 9 and make it calling INT $40 then.

#11 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 08 January 2006 - 10:11 AM

;) I should have seen that ... :banghead:

Just follow marcos advice

#12 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 08 January 2006 - 10:23 AM

nothing from the Marco's variants is worked. not call far, not jmp far, and not changing 9h interrupt to unused and calling this int.
but. if i disable marco's modules (so I use original pascal readln procedure) - all works, not fine but works!
as fine as when I use original readln and not replace int9h (not confirmed input, because of exe have different scancode than enter on pc).
so as I think the problem is in Marco's readln procedure ;)
Marco, please send me a sources of your modules, I repeat my email: xxakep(at)inbox.ru

#13 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 08 January 2006 - 12:47 PM

hm ... are you sure it really changes the int if you don't use marcos lib?

Btw. why do you need to change the interrupts?

Here is the way I do it in ASM:

;(C) 2006 Marcus H?hnel / huhn_m
;Extracted from the MLC2 sources.
;Code is licensed under the GPL version 2 www.gnu.org/licenses/gpl.html

oldISR_Kbd_off dw 0
oldISR_Kbd_Seg dw 0

KeyPressed db 0

_SetupKeyboard proc
	PUSH AX ES
	
	CLI
	XOR AX,AX
	PUSH AX
	POP ES
	MOV AX,word ptr ES:[09h*4]
	MOV word ptr CS:[oldISR_kbd_off],AX	
	MOV word ptr ES:[09h*4],offset __KeyboardISR
	
	MOV AX,word ptr ES:[09h*4+2]
	MOV word ptr CS:[oldISR_kbd_seg],AX
	MOV word ptr ES:[09h*4+2],seg __KeyboardISR
	
	STI

	POP ES AX
	ret
endp

_ResetKeyboard proc
	PUSH AX ES
	
	CLI
	XOR AX,AX
	PUSH AX
	POP ES
	MOV AX,word ptr CS:[oldISR_kbd_off]
	MOV word ptr ES:[09h*4],AX
	
	MOV AX,word ptr CS:[oldISR_kbd_seg]
	MOV word ptr ES:[09h*4+2],AX
	
	STI

	POP ES AX
	ret
endp

__KeyboardISR proc	
	PUSH DS
	PUSH @CODE
	POP DS
	MOV DS:[keyPressed],Yes
	POP DS
	pushf
	call dword ptr CS:[oldISR_kbd_Off]
	iret
endp


#14 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 08 January 2006 - 01:45 PM

hm ... are you sure it really changes the int if you don't use marcos lib?

yes, I shure, because I leave afxsys enabled, or include dos.tpu and use get/setintvects procedure, which is similar.

Btw. why do you need to change the interrupts?

because I need to intercept some keypresses in any moment, for example in calculation process. esc - to terminate calculation and exit to main menu, up and down keys - to change contrast. if you know how to do this without replacing interrupt - please explain :)

Here is the way I do it in ASM:

how you process pressed keys before original interrupt? e.g. what happen if some key pressed? and how you react on this? how you know what key is pressed? please explain to me


I need only to react on some keys in any moment and to input numbers when required, confirmed by exe key. how to realize readln procedure without original interrupt? if we do this there are no need in original int9h.

#15 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 08 January 2006 - 03:22 PM

For how to use the keyboard (keycodes etc) see the Programming Guide by Olivier Coupelon (french) or its english translation on the algebrafx page (see link page).

If you want to interrupt a look you can also querry the keyboard during the loop to see if a key was pressed. I'm not sure about how marco implemented it but I think it is in his libs.

You only need to change the keyboard interrupt if you:

*Want to prevent SHIFT+AC/ON from turning of the calc
*Want to prevent the changing of contrast using the SHIFT+Left/Right keys
*Want to interrupt the program at ANY given time not only in a loop but in a lot of places where placing a keyboard polling would be useless.

Have you ever written an ISR? If not think about it carefully since the process is verry error prone and errors in ISRs are not always obvious since they can change the program flow at nearly ANY given time!

#16 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 08 January 2006 - 03:32 PM

I never wrote an ISR before.
ok, i need only to check inside a loop if an exe key was pressed. how to do it fast? example:

procedure calculation;
begin
 repeat
 if check_esc=true then exit;
 generate_reposition;
 check_reposition;
 until last_reposition;
end;

how to implement check_esc fastly? because of repeating this cycle is about 64000 times fo 6-digit number an so on, if I try to check a key by interrupt this will slow down a calculation significantly. but if I check only a variable there will be much faster then when calling an interrupt(e.g. when using marco's functions keypressed, readkey, etc.)

#17 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 08 January 2006 - 05:24 PM

hmm ... but take into account that most time is wasted by the ISR anyways.
I would try using keypressed and if it is true branch to another part of the
function and check what key and if it justifies and abortion. Example:

procedure calculation;
begin
repeat
if not keyPressed then
 generate_reposition;
 check_reposition;
else
 if Key = ESC then
   break
 else
  generate_reposition;
  check_reposition;
until last_reposition;
end;

If the compiler translates this code intelligently then this should only be slowed down significantly if a key (other than esc) is pressed during the whole loop.

#18 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 08 January 2006 - 06:04 PM

wow :o thank you :) such variant was not came to my mind :) I will try it soon.
but I also need Marco's sources of AFXTP because I want that program exits to main menu too, when an esc key pressed during input.

and thank you all for help!

#19 Orwell

Orwell

    Casio Overlord

  • Members
  • PipPipPipPipPipPipPip
  • 777 posts
  • Gender:Male
  • Location:Paris - France

  • Calculators:
    Casio AFX 1.02 / Casio ClassPad 300

Posted 09 January 2006 - 04:29 PM

how to implement check_esc fastly? because of repeating this cycle is about 64000 times fo 6-digit number an so on, if I try to check a key by interrupt this will slow down a calculation significantly. but if I check only a variable there will be much faster then when calling an interrupt(e.g. when using marco's functions keypressed, readkey, etc.)

Again, are you really certain that you need to implement such a heavy method? :blink:
If the goal is simply to find a number matching those criteria's, you should not generate the complete list and pick a number at random in it, that's quite too long :o
Maybe I didn't exactly understand what you want, but you should allways try to optimize your program first before thinking that you need a more powerful language... Marco suggested another code for this, what about it?

#20 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 09 January 2006 - 05:31 PM

Orwell, you and Marco are not exactly understand what I want :) my program doesn't generate all repositions and save it to array. It is generate reposition by order, e.g. generate first - check with previous answers, if true - ask you to input answer for this number. if false - generate next reposition, and repeating this until all repositions for defined n is checked. if number not finded - therefore your answers was wrong.

this program search your number, not guess its number to you! therefore random generate in this prog not needed at all! marco's algorithm is not optimal because it generate reposition by its number. but I need to generate they constantly. if I use marco's algorithm then I need to calculate number of all repositions and then use cycle for i:=0 to number_of_repositions-1.
algorithm that I use generate reposition by those parameters: array of one previous reposition, number of digits, use 0 or not (e.g. use 0,1...9 or 1,2...9 digits). and its works faster then Marco's one, but not enough faster, because its generates all repositions for 6 digit number ~ 1-1.5 minutes. this is quite long for real-time game.

I use this algorithm for generatin repositions:
const
  alphabet : string[26] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
type
  barray = array [1..100] of byte;
var
  b : barray;
  N,M,i,j,k : byte;
  z : longint;

Procedure WriteB(B:barray);
  begin
	Inc(Z); Write (Z:3,' : ');
	for i:=1 to M do write(alphabet[b[i]]);
	writeln;
  end; 
Procedure SwapB(var B:barray;i,k:byte);
  var x : byte;
  begin
	x:=B[i]; B[i]:=B[k]; B[k]:=x;
  end;

Procedure PermuteAll(B:barray;N:byte);
  var i,k,j : byte;
  begin
	WriteB(B);
	while (true) do
	begin
	  i:=N;
	  while (i>0) and (B[i]>=B[i+1]) do i:=i-1;
	  if i=0 then exit;
	  for j:=i+1 to N do
		if (B[j]>B[i]) then K:=j;
	  SwapB(B,i,k);
	  for j:=i+1 to (i+((N+1-i)div 2)) do SwapB(B,j,N+i+1-j);
	  WriteB(B);
	end;
  end;

begin
  readln(N,M);
  for i:=1 to M do b[i]:=i;
  PermuteAll(B,M);
  {in this place I check generated number, e.g. testnumber(b);}
  while (true) do begin
	  i:=M;
	  while (i>0) and (b[i]=N-m+i) do Dec(i);
	  if i=0 then exit;{your answers was wrong!}
	  Inc(B[i]);
	  for j:=i+1 to M do B[j]:=B[j-1]+1;
	  PermuteAll(B,M);
	  {also testnumber(b);}
	end;
  readln;
end.
this is not mine algorithm, and I only modified it to generate digits, not letters, and not using Z to write position :) and simply insert it in my program. can you all help me with optimising it? or can you know similar but faster algorithm?

#21 Marco

Marco

    Casio Freak

  • Members
  • PipPipPipPip
  • 185 posts
  • Location:Dresden, Germany

  • Calculators:
    Casio CFX 9850G (broken),
    Casio CFX 9850GB,
    Casio Algebra FX 2.0 Plus

Posted 09 January 2006 - 07:59 PM

It is generate reposition by order, e.g. generate first - check with previous answers, if true - ask you to input answer for this number. if false - generate next reposition, and repeating this until all repositions for defined n is checked. if number not finded - therefore your answers was wrong.

So what you need need is a game AI; human does an arrangement of digits and AI must guess it in a count of moves? Hm... that's quite tricky.

Note that even if you find a matching move with your algorithm, this isn't the best one possible. If a human plays master mind, he also doesn't take any move possible, but chooses good constellations increasing his chance to guess with the next move, e.g., alternate 2 of 4 colors and so on (--> good game AIs use more than one move depth in thinking + heuristic methods).

However, to speedup your algorithm, it should help a lot already to do not call a procedure within the time - critical PERMUTE_ALL, thus integrate SWAPB directly. Then, precompute constants in for - loops that they aren't computed each iteration anew. Instead of div 2, use shr 1. On time critical routines, put less worth on structured programming. Use GOTOs instead of WHILE TRUE or where ever it would save time. Use FOR instead of WHILE (i>0) ...

Procedure PermuteAll(B:barray;N:byte);
  var i,k,j : byte;
  begin
	WriteB(B);
	m1:

	for i := N downto 0 do if B[i]<B[i+1] then goto m2;
	exit;

	m2:
	for j := i+1 to N do if B[j]>B[i] then K:=j;
	x := B[i];
	B[i] := B[k];
	B[k] := x;

	y := i+(N+1-i) shr 1;
	z := N+i+1
	for j := i+1 to y do
	begin
	  x := B[j];
	  B[j] := B[z-j];
	  B[z-j] := x;
	end;

	writeB(B);
	goto m1;
  end;
Don't know how much faster it'll be, but you could try to replace the sequence between M1: and GOTO M1 by assembler. E.g., a SWAP(B,I,K) sequence could be replaced by

asm
  xor bh,bh
  mov bl,i
  mov al,[bx+offset B]
  mov bl,j
  xchg [bx+offset B],al
end;
wich for sure would give a speedup.

Got your PM btw., and yes, I've not forgot to send you the AFXTP sources. I'll do this today, in your time zone it'll be tomorrow however ;)

#22 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 09 January 2006 - 08:55 PM

So what you need need is a game AI; human does an arrangement of digits and AI must guess it in a count of moves? Hm... that's quite tricky.
Note that even if you find a matching move with your algorithm, this isn't the best one possible. If a human plays master mind, he also doesn't take any move possible, but chooses good constellations increasing his chance to guess with the next move, e.g., alternate 2 of 4 colors and so on (--> good game AIs use more than one move depth in thinking + heuristic methods).

procedure testnumber checks not only one previous answer! on the first time (when no prev.ans.) in checks nothing! on the second - one previous ans, on the third - two previous answers and so on. there is an array where up to 32 previous numbers with answers is stored :) and for 6-digit number there ~6 answers enough to find your guessed number. so algorithm is good. for human is impossible to check 64000 combinations with prev.answers to find right number, for program - it is more than real. but generation of repositions is waste many time, so I need only to speed up reposition generation. thank you for examples of optimisation, I'll try it soon (after 2 exams in university). Maybe you can write in asm a cows function? it is used in procedure testnumber to check two numbers and return a number of cows and number of bulls. it's source:
type numb: array[0..9] of integer;

function cows(n1,n2:Numb):byte;
{compares two numbers and return result as 
<number of bulls>*10+<number of cows>}
var
 i1,i2 : byte;
 a : byte;
begin
{comparing all digits of the first number with all digits of the second number}
 a:=0;
 for i1:=1 to Sgn do
  for i2:=1 to Sgn do
   if n1[i1]=n2[i2] then
	if i1=i2 then a:=a+10 {'bull' appears}
	else inc(a);
 cows:=a;
end;
but function must have same parameters(e.g. works with array) and return result as original. because I don't know how to give parameters to asm procedures and how to process them in asm too :unsure:

oh, and if you can, please when posting asm code, please explain what each string is exactly do (e.g. write a comment in the end of each string), I want not only to copy code, but to understand it ;) so, if it is not hard for you, please write a comments, ok?

#23 Marco

Marco

    Casio Freak

  • Members
  • PipPipPipPip
  • 185 posts
  • Location:Dresden, Germany

  • Calculators:
    Casio CFX 9850G (broken),
    Casio CFX 9850GB,
    Casio Algebra FX 2.0 Plus

Posted 10 January 2006 - 09:51 PM

I sent you the AFXTP II sources now (sorry, had no time left yesterday, but now the mail is sent :))

but function must have same parameters(e.g. works with array) and return result as original. because I don't know how to give parameters to asm procedures and how to process them in asm too

Quite simple, use it as you do in a high level language. E.g.,

procedure a(b: word); assembler;
asm
  mov cx,b
end;
is allowed. The compiler will replace "mov cx,b" by "mov cx,[bp+offset b]" by itself. If you have VAR parameters, treat them as pointers. And retrun values are placed in al (8 Bit), ax (16 bit) or dx:ax (32 bit) register.

#24 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 14 January 2006 - 02:32 PM

well, with help of Marco I finally replaced this construction:
x:=B[i];
B[i]:=B[k];
B[k]:=x;
with assembler:
asm
 mov si,i
 mov di,k
 mov al,byte ptr B[si-1]
 xchg al,byte ptr B[di-1]
 mov byte ptr B[si-1],al
end;
Marco's variant with "[bx+offset B-1]" didn't work, but "byte ptr B[si-1]" works ok:) I don't know why, maybe need to specify a segment?...

Also Marco sent me sources of AFXTP and I've modified afxcrt and afxstdio, so cancellig of input by esc key works well:)) I think standard IO functions didn't support emty input with only #13#10 at all. so I simply have added a variable input_result, and when esc pressed, I set zero to input buffer (fith final #13#10 of course), and input_result:=1, because need to make difference between inputting a zero and pressing esc (in both cases placed zero to input buffer).

replacing swap with assembler didn't gave big speed difference (for 6 digits time decreased from 69 seconds to 64). I've tried to comment out a testnumber procedure, and.. time is 2 seconds only! so really need to optimise testnumber (in which also called cows function) by integrating cows function in it, and by replacing all this construction with assembler, I think.
I need help in assembler, I don't know how to make a nested loops, and how to work with records:( Can anyone help me with rewriting this code in asembler?
for i:=1 to nstep do
 begin
  a:=0;
   for i1:=1 to 9 do
	for i2:=1 to 9 do
	 if n[i1]=info[i].n[i2] then
	  if i1=i2 then a:=a+10
	   else inc(a);
  if a<>info[i].answer then exit;
 end;
where: a,i,i1,i2:byte, n:array[1..9] of byte,
info: array [1..32] of record{n:array[1..9] of byte, answer:byte}

#25 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 14 January 2006 - 05:05 PM

Assembler code:

MOV CX,nStep;Counter
@@loop: 
  XOR AX,AX
  MOV BL,1;BL = i2
  MOV BH,0;BH = i1
  @@InnerLoops:
	INC BH
  ;Do comparision here. (See note below!!)
	JNE @@continueLoopBlock
	INC AX
	CMP BH,BL;if i1=i2 then
	JNE @@ContinueLoopBlock;else
	ADD AX,9;only plus 9 since 1 is added in any case! (see inc AX above)
	@@ContinueLoopBlock:
	INC BH
	CMP BH,9
	JNE @@InnerLoops
	INC BL
	XOR BH,BH
	CMP BL,10
  JNE @@InnerLoops
  MOV SI,CX
  ADD SI,offset info
  CMP AX,word ptr DS:[SI].anwser;//See comment below! Not sure
  JE @@end1
loop @@loop
@@end1:

Didn't test if it really runs but it should and is quite optimized.
However, I don't know how to address structures (records) from PASCAL
in ASM. Please wait for marco to tell you if you don't know yourself.

*edit
damn ... the IPB software doesn't seem to support identing ... now it looks ugly.
*edit2
Fixed ;)

#26 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 14 January 2006 - 09:30 PM

thank you, huhn_m.

Please wait for marco to tell you if you don't know yourself.

:) yes, I don't know too. so, waiting for Marco...

BTW, does anyone need a russian version of the Calc-to-PC cable? I've translated it to english in photoshop:) its different from another versions by added LEDs indicating "read", "write" and "power", which is very useful while "debugging" cable and also while using it too. All russian details are replaceable by non-russian analogs. Author is not I am, I've only translated it, but I shure that author haven't mind against uploading his scheme;)
I've made a cable by this scheme by myself and its really works. it's cool, since when I tried max232 version before, its not worked at all:(
also I have a PCB layout for this scheme, but for the moment it with some mistakes, which I've corrected after assembling scheme, so I can carrect this mistakes on my PCB layout too.

#27 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 14 January 2006 - 10:53 PM

you could upload it somewhere or mail it to me (huhn ( a_ t ) casiocalc (d_o:t) org) and I could include it into the tutorials section (along with the other schemes).

Thanks!

(oh. and thanks for you interrest in MLC2. )

#28 2072

2072

    Casio over god

  • Admin
  • PipPipPipPipPipPipPipPip
  • 1564 posts
  • Gender:Male
  • Location:Somewherebourg
  • Interests:Alternative states of consciousness, programming, making things work the best they possibly can.

  • Calculators:
    AFX2 ROM 1.02, CFX-9940GT+, FX-180P-Plus

Posted 15 January 2006 - 08:30 AM

just a side not, there is no need to obfuscate your email address, the forum does it for you:

2072 AT 2072productions.com

#29 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 15 January 2006 - 09:11 AM

hm thanks. didn't know that ... I just think that if such a popular software uses such measures the bot writers do just adopt to the way the addresses are written. I would need to be random to generate effective protection.

But then, on the other side, I never go spam to either my mh-development.de or my casiocalc.org mail addresses.

#30 Marco

Marco

    Casio Freak

  • Members
  • PipPipPipPip
  • 185 posts
  • Location:Dresden, Germany

  • Calculators:
    Casio CFX 9850G (broken),
    Casio CFX 9850GB,
    Casio Algebra FX 2.0 Plus

Posted 15 January 2006 - 09:14 AM

Records work this like:

{normal}
type r = record
		   a: byte;
		   b: byte;
		 end;

var x: r;
asm
  mov al,x.b
end;

{pointer}
var y: ^r;
asm
  mov bx,y
  mov al,[bx+r.b]
end;
You will not be able to use pointer method however, cause indexed adressing seems not to work on your special Turbo Pascal version ;) (see below)

Marco's variant with "[bx+offset B-1]" didn't work, but "byte ptr B[si-1]" works ok:) I don't know why, maybe need to specify a segment?...

I don't believe you for 2 reasons :D:

I) "ptr B[si-1]" is exactly equivalent to "[si+offset B-1]",
II) I tested the code I mailed you myself this time and it worked. Probably you made an error some elsewhere (e.g. register initialisation cause you used one time BX and one time SI as index register)?

No segment specification needed; instructions use always DS by default except you use SP or BP an index register.

#31 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 15 January 2006 - 07:03 PM

2 Marco:
1.
asm
 mov si,i
 mov di,k
 mov al,byte ptr B[si-1]
 xchg al,byte ptr B[di-1]
 mov byte ptr B[si-1],al
end;
my version of code is inserted instead of x:=B[i]; B[i]:=B[k]; B[k]:=x; directly, and have no problems. if I use mov al,[si+offset B*]; where for different * al is:

*: -1 0 1 2 3 4 5 6 7 8
al: 36 2 131 46 36 36 6 139 62 2

(array B I filled with for j:=1 to 9 do B[j]:=j. e.g. B={1,2,3,4,5,6,7,8,9})

so, instead of 1,2,3,.... in the al I have strange numbers :blink:

and with damn debugger of turbo pascal I cannot view a memory directly, so I don't understand, what are numbers, that is placed into al register.

2. can you try to correct a huhn_m's algorithm with those what you say about accessing records? I cannot fully understand both you and him code together, sorry :)

2 huhn_m I just sent you a pcb layout too, but I dont know how to correct mistakes in p-cad directly, cuz its change all previous layout too. so, I just use printscreen and corrected this in Photoshop ;)

#32 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 15 January 2006 - 09:11 PM

hmm. I've tried to debug little proggie (in winG100 instead of damn pascal debugger) in which only a filling of array and a swap procedure in assembler. and if I use
mov al,byte ptr[si-1] its compiled into
mov al,byte[bp+si-0x000b].
but when I use Marco's version,
mov al,[si+offset B-1] it is compiled to
mov al,byte[si-0x000b] !!!
so, in Marco's version for some reason bp is not present.
Did huhn_m or Marco or maybe Orwell knows why? I'm as usual don't :D what in the bp register? and why its not added to pointer if use [..offset..] instead of byte ptr[..] ???

#33 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 15 January 2006 - 10:20 PM

I don't have the opcodes near me rigght now but I believe that there is no opcode that allows the addressing of SI+pointer+offset.
Did you look at the previous lines? maybe SI is modified somewhere, optimized by the compiler?

(This is why I LOVE coding in ASM. the processor only does exactly what you tell it. No "optimizations" by the compiler that can go wrong ...)

Thanks for the pcb. I'll look into it on wedness day since I have to go to munich on tuesday ... so no time ;)

#34 Marco

Marco

    Casio Freak

  • Members
  • PipPipPipPip
  • 185 posts
  • Location:Dresden, Germany

  • Calculators:
    Casio CFX 9850G (broken),
    Casio CFX 9850GB,
    Casio Algebra FX 2.0 Plus

Posted 15 January 2006 - 10:41 PM

>Did huhn_m or Marco or maybe Orwell knows why?

BP is the stack frame base register. This means you probably have B as a parameter or local variable of a procedure (that's why I told you to don't use B as a parameter in my mail). When entering a procedure, current SP is loaded into BP and stack variables adressed relative to BP then.

In my code it worked because I tested with a global variable B. If youn want to keep it local, use either "[bp+si+offset B-1]" or your version. It doesn't matter wich one, for the compiler it's both the same.

Next time you should post the complete code so such things can't happen ;) However, if you need still want to make it faster, just post the complete code of the cows function again with all things that belong to it (e.g. variables and data structures used by cows, how to help you else?). Also what has the cows function to do with permuteall and swap function? Is the cows functions the only time critical one? What about the caller of cows?

#35 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 16 January 2006 - 12:24 AM

:D ok Marco, this is fragments of my source:
Const MaxSgn=9;
Sgn=9;
Type s=0..MaxSgn;
Numb=array[1..9] of byte;
type Step = Record
n : Numb;
answer : byte;
end;
Game = array[1..32] of step;
var NStep:longint;
Info:game;
dlina : byte;
tm1,tm2: longint;
xit:boolean;

procedure testnumber(n:numb);
Var
 i,nm1,nm2:byte;
 i1,i2,a:byte;
begin
{I've integrated cows function directly to testnumber procedure}
 for i:=1 to nstep do
  begin
  a:=0;
  for i1:=1 to dlina do
   for i2:=1 to dlina do
	if n[i1]=info[i].n[i2] then
	 if i1=i2 then a:=a+10}
	  else inc(a);
  if a<>info[i].answer then exit;
  end;
  if (cows(n,info[i].n))<>info[i].answer then exit;
...............................................
{there, if no exit from procedure in previous line,
n is wrote and calc asks for next answer, that it stores in info[i].answer., and then procedure testnumber exits and permuteall is continued}

Procedure PermuteAll(B:numb;N:byte);
  var i,j,k,w,x,y,z : word;
  label m1,m2;
  begin
   K:=1;
   testnumber(B);
   if mem[$40:$AF]=$01 then cancelscreen;
   if xit=true then exit;
   m1:
   i:=N;
   while(i>0)and(B[i]>=B[i+1]) do dec(i);
   if i=0 then exit;
   for j:=i+1 to N do if (B[j]>B[i]) then K:=j;
   asm
	mov si,i
	mov di,k
	mov al,byte ptr B[si-1]
	xchg al,byte ptr B[di-1]
	mov byte ptr B[si-1],al
   end;
   y:=i+((N+1-i) shr 1);
   z:=N+i+1;
   for j:=i+1 to y do
	begin
	 w:=z-j;
	 asm
	  mov si,j
	  mov al,byte ptr B[si-1]
	  mov di,w
	  xchg al,byte ptr B[di-1]
	  mov byte ptr B[si-1],al
	 end;
	 end;
   testnumber(B);
   if mem[$40:$AF]=$01 then begin cancelscreen;if xit=true then exit;end;
   goto m1;
  end;
so, I think this code is enough to make optimisations B)

BTW, what debugger I should use in win98 to debug exe's for 286 processor? (no SoftICE please, cuz I'm use VMware, and is no need for kernel-mode debugger ;) ) Ollydbg can't work with exe's from turbo pascal 6.0....

#36 2072

2072

    Casio over god

  • Admin
  • PipPipPipPipPipPipPipPip
  • 1564 posts
  • Gender:Male
  • Location:Somewherebourg
  • Interests:Alternative states of consciousness, programming, making things work the best they possibly can.

  • Calculators:
    AFX2 ROM 1.02, CFX-9940GT+, FX-180P-Plus

Posted 16 January 2006 - 01:47 AM

hm thanks. didn't know that ... I just think that if such a popular software uses such measures the bot writers do just adopt to the way the addresses are written. I would need to be random to generate effective protection.

But then, on the other side, I never go spam to either my mh-development.de or my casiocalc.org mail addresses.



No, it's not an original feature of the forum, I've made some improvements :) So it must be the only IPB forum that is able to do that... And bots have an infinit number of email addresses to harvest if they, by accident, find this link: http://www.casiocalc.org/members/ :lol:

#37 huhn_m

huhn_m

    Casio Maniac

  • [Legends]
  • PipPipPipPipPipPipPipPip
  • 1957 posts
  • Gender:Male
  • Location:Germany / Dresden
  • Interests:Assembler(!!!)
    Computers and Programming
    Operating Systems
    Programmable Calculators
    Maths and everything arround it

  • Calculators:
    FX-82SX / AFX 2.0+ (ROM 1.03) / FX 1.0+ (ROM 1.03)

Posted 16 January 2006 - 02:58 PM

thanks 2072! this is nice. Then I think i can trust it :)

btw. nice site. ... maybe I'll add some of the mail addresses to my address book :D

[ / offtopic]

#38 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 17 January 2006 - 10:10 PM

Marco! where are you? :unsure: I've posted my sources. Still waiting for your reply :)

#39 Marco

Marco

    Casio Freak

  • Members
  • PipPipPipPip
  • 185 posts
  • Location:Dresden, Germany

  • Calculators:
    Casio CFX 9850G (broken),
    Casio CFX 9850GB,
    Casio Algebra FX 2.0 Plus

Posted 18 January 2006 - 03:51 PM

first, modify the STEP data structure that you cann access ANSWER field faster and the fields of GAME, too:

type step = record
answer: byte; {adress 0}
n: numb;
dummy: array[0..4] of byte; {make STEP structure 16 Bytes in size}
Then, make DLINA a word variable and use this code for testnumber:

{be CX = i, i1 = SI, i2 = BX, a = AX}
mov cx,nstep
dec cx

{can nstep be 0? of not, the next line is not needed:}
jz @mend

xor ax,ax
mov si,dlina
@mouter: {outer loop}

mov dl,[si+offset n] {DL := n[i1]}
mov di,cx
shl di,4 {SI = 4 shl 4}

mov bx,dlina
@minner: {inner loop}

{first ifthen; since STEP is 16 bytes no, @INFO[i] = i shl 4 + offset INFO - 16 with DI= i shl 4}
{and @n[i2] is i2 is BX}

cmp dl,byte [DI+BX+offset info-16]
jnz @m1

cmp si,bx {if i1=i2}
jnz @m2
add ax,9 {9, not 10, cause next instruction is INC}

@m1:
inc ax

@m2:

???? * (see below)

dec bx
jnz @minner {loop inner}
dec si
jnz @mouter {loop outer}

Then, in PERMUTEALL - procedure use just one call of TESTNUMBER. Means, instead of

testnumber(B);
  if mem[$40:$AF]=$01 then cancelscreen;
  if xit=true then exit;
  m1:

  ...

  testnumber(B);
  if mem[$40:$AF]=$01 then begin cancelscreen;if xit=true then	   
  exit;end;
  goto m1;

use
if xit=true then exit;

   m1:
  testnumber(B);
  if mem[$40:$AF]=$01 then begin cancelscreen;if xit=true then	   
  exit;end;

  ...

  goto m1;
NOTE THAT I DIDN'T FOUND where you set XIT to true, maybe strip the XIT thing if not needed!

Because now, there's just one call of TESTNUMBER, replace it by inserting the TESTNUMBER Code directly so you save the call.

*) For ???? I'll insert code this evening, I must catch my bus now ;)

#40 Guest_feanor_*

Guest_feanor_*
  • Guests

Posted 18 January 2006 - 04:40 PM

NOTE THAT I DIDN'T FOUND where you set XIT to true, maybe strip the XIT thing if not needed!

xit is assigned to true or false in cancelscreen procedure, which is used only for terminating calculations by user request, so it doesn't need to be optimised ;)

Because now, there's just one call of TESTNUMBER, replace it by inserting the TESTNUMBER Code directly so you save the call.

there is no need to insert _all_ testnumber code, cuz time critical only that part what I've posted before. Other part is only I/O part (outputs current number and inputs answer for it).

anyway, thank you! :)




3 user(s) are reading this topic

0 members, 3 guests, 0 anonymous users