Welcome, Guest |
You have to register before you can post on our site.
|
Online Users |
There are currently 703 online users. » 0 Member(s) | 698 Guest(s) Bing, Facebook, Google, Twitter, Yandex
|
Latest Threads |
Includes in ASM
Forum: How-To & Tutorials
Last Post: bracckets
04-04-2024, 12:17 AM
» Replies: 2
» Views: 563
|
Intermittent errors
Forum: Help & Support
Last Post: zarsoft
03-12-2024, 12:39 PM
» Replies: 0
» Views: 315
|
Store array information i...
Forum: Help & Support
Last Post: rbiondi
03-10-2024, 09:42 PM
» Replies: 0
» Views: 406
|
ScrollLeft function scrol...
Forum: Bug Reports
Last Post: rbiondi
03-07-2024, 03:57 PM
» Replies: 2
» Views: 821
|
string.bas errors when co...
Forum: Bug Reports
Last Post: rbiondi
03-01-2024, 10:10 AM
» Replies: 2
» Views: 726
|
Using Beepola with ZX BAS...
Forum: How-To & Tutorials
Last Post: edtoo
02-29-2024, 09:47 AM
» Replies: 15
» Views: 32,831
|
Johnny Bravo
Forum: Gallery
Last Post: zarsoft
02-11-2024, 11:20 PM
» Replies: 0
» Views: 485
|
Compiling +D G+DOS progra...
Forum: ZX Basic Compiler
Last Post: boriel
01-22-2024, 08:32 AM
» Replies: 4
» Views: 8,674
|
VAL = ? (solved)
Forum: Bug Reports
Last Post: zarsoft
01-03-2024, 11:44 PM
» Replies: 8
» Views: 3,243
|
Wrong math (solved)
Forum: Bug Reports
Last Post: zarsoft
01-03-2024, 11:38 PM
» Replies: 4
» Views: 1,767
|
|
|
Bit Shifts |
Posted by: britlion - 02-22-2010, 11:39 PM - Forum: How-To & Tutorials
- Replies (11)
|
|
C provides bit shift functions >> and << which aren't available in Sinclair or ZX basic. Since I happened to have a need for such a function, I decided to drop them up here. Again, this is something that's easy on the CPU.
They work with Long Unsigned integers - and will work fine with smaller values, or you can use them as a template for 16 or 8 bit versions in assembler.
Code: FUNCTION bitL(num as uLong) as uLong
REM we get DEHL as uLong
asm
SLA L
RL H
RL E
RL D
END asm
END FUNCTION
Code: FUNCTION bitR(num as uLong) as uLong
REM we get DEHL as uLong
asm
SRA D
RES 7,D ; makes a zero shift into D instead of what was there originally. If you want this to work with signed numbers, you could always change it to res 6,d.
RR E
RR H
RR L
END asm
END FUNCTION
|
|
|
Faster Trigonometry |
Posted by: britlion - 02-20-2010, 03:39 AM - Forum: How-To & Tutorials
- Replies (3)
|
|
Sometimes we're willing to lose accuracy for speed. ZX BASIC uses the spectrum's ROM routines for many of its math functions, and as a result of them being general purpose routines that use 40 bit numbers, well, they can be a bit slow sometimes.
See my article on square roots, for a good example.
Here is a routine to produce SIN(angle) - where angle is in degrees. It uses a lookup table to calculate sin values, and it's a very quick and dirty method, in that it only actually knows 32 angles, and those to only 8 bit precision. It does linear interpolation between these known angles, however, so that does improve things somewhat.
I was actually surprised how precise it was - it's good for at least 2 decimal places, probably 3 as a rule of thumb. The average error is 0.002 That's probably good enough for games that need to calculate angles. It's about 4-5 times faster than the SIN(FLOAT) function, and not even written in native assembler.
If you need better accuracy, it would be fairly easy to change the method to use a bigger table - perhaps 2 bytes per entry, even.
Remember to work out COS and TAN can also use this function - COS is SIN(90+x) and TAN is SIN(x)/COS(x). It should be easy to write COSINE and TANGENT functions to do the adjustments and call the SINE function.
(And this one I didn't copy. It's all mine! Bugs and all. And now it's free for anyone to use.)
Code: FUNCTION SINE(num as FIXED) as FIXED
DIM quad as byte
DIM est1,dif as uByte
while num>360
num=num-360
end while
IF num>180 then
quad=-1
num=num-180
ELSE
quad=1
END IF
IF num>90 then num=180-num: end if
num=((num*31)/90)
dif=num : rem Cast to byte loses decimal
num=num-dif : rem so this is just the decimal bit
est1=PEEK (@sinetable+dif)
dif=PEEK (@sinetable+dif+1)-est1 : REM this is just the difference to the next up number.
num=est1+(num*dif): REM base +interpolate to the next value.
return (num/255)*quad
sinetable:
asm
DEFB 000,013,026,038,051,064,076,088
DEFB 100,112,123,134,145,156,166,175
DEFB 184,193,201,209,216,223,229,234
DEFB 239,243,247,250,252,254,255,255
end asm
END FUNCTION
|
|
|
Sometimes it just goes crazy |
Posted by: britlion - 02-20-2010, 03:03 AM - Forum: Bug Reports
- Replies (1)
|
|
I was having trouble with a variable not being where I expected. In the end, I have this code:
Code: FUNCTION SINE(num as FIXED) as FIXED
{skipped some code]
PRINT at 0,0;((num*32)/90)
PRINT INT ((num*32)/90)
So num is a fixed, and the skipped code makes it 0<=num<=90
The routine prints out for those two:
0.35554504......
23301
Now, I'm thinking that INT(0.35) is 0. The compiler landed about 23,000 too high on that one.
Any idea why?
|
|
|
Compiler Speed Trials |
Posted by: britlion - 02-18-2010, 04:20 PM - Forum: ZX Basic Compiler
- Replies (74)
|
|
I know that ZX Basic is amazing, but I was wondering how it stood up to other basic compilers that were around for use on the ZX Spectrum. We know that Hisoft basic was pretty fast, for example, and LCD mentioned another compiler the other day that was pretty amazing too.
Let me borrow from an article in Crash Magazine: http://www.crashonline.org.uk/19/compilers.htm
In this article, Simon Goodwin talks about several compilers. Hisoft Basic isn't one of them - it wasn't out yet. He doesn't list the benchmarks, either; but they can be interpolated from this:
Code: Benchmark BM1 : A null-action FOR, REPEAT or DO loop, executed
1000 times.
Benchmark BM2 : A null-action explicitly-coded loop executed
1000 times.
Benchmark BM3 : BM2 plus A=K/K*K+K-K in the loop.
Benchmark BM4 : BM2 plus A=K/2*3+4-5 in the loop.
Benchmark BM5 : BM4 plus a branch to null-action subroutine
from inside the loop.
Benchmark BM6 : BM5 plus an array declaration M(5), and a
null-action FOR loop (of 1-5) also in the
loop.
Benchmark BM7 : BM6 plus M(L)=A in this 1-5 loop.
Benchmark BM8 : A square function, log function and sin
function in an explicitly-coded FOR loop,
repeated 100 times.
Benchmark BM9 : Prime numbers in the range 1-1000 are printed
to the screen, calculated in an outer loop of
1000 and an inner loop of 500, with no tricks
at all. This is a very bad prime number
routine indeed, but a very useful basis for
inter-machine, interpreter and compiler
comparisons.
Simon didn't use Benchmark 9, and I can see why - it's not clearly specified. BM1 to BM8 are pretty clear, however.
My own personal testing with Sinclair Basic gave very slightly differing results. In all cases, my programs were very slightly faster than the timings Goodwin gave in the magazine article. Perhaps he specified things a little differently, perhaps he was using a stopwatch in hand, and human error was the result. Perhaps it was a different version of the ZX Spectrum used. I got the computer to time the programs using the 50 frames per second interrupt timer. For very fast running programs I increased the number of loops by a factor 10 or 100 and estimated back down.
The compilers goodwin tested were:
A Mehmood's "Compiler".
MCODER
Softek's FP and IS
And a little cheekily, Zip 1.5. He wrote that himself, I believe.
The first two rows are for Sinclair Basic. The first being Simon Goodwin's numbers, the second being my own. All times are in seconds, smaller is better.
Code: BM1 BM2 BM3 BM4 BM5 BM6 BM7 BM8 BMDRAW
Sinclair 4.46 8.46 21.56 19.82 25.34 60.82 87.44 23.30 80.18
Boriel's ZX BASIC 0.038 0.032 0.30 0.15 0.16 0.328 2.20 24.0
ZX Basic 1.26-r1603 -O3 0.94 20.78 (17.14 with fSin)
ZX Basic 1.2.8-s682 -O3 0.88 20.56 (16.94 with fSin) 21.14
ZX Basic 1.2.8-s758 -O3 0.90 20.76 (17.10 with fSin) 21.32
HiSoft FP 0.82 1.34 7.26 7.30 7.32 12.52 14.40 21.9
HS Integer 0.042 0.67 0.08 0.088 0.334 0.50 10.76
Mehmood * 0.065 9.0 4.2 4.2 * * *
ZIP 1 .5 0.031 0.064 0.194 0.108 0.115 0.29 0.46 *
TOBOS 0.58 0.82 2.02 1.76 2.34 6.68 8.72 0.746
SOFTEK FP 1.75 2.1 8.7 9.4 9.4 19.7 24.0 22.5
SOFTEK IS 0.058 0.076 0.57 0.98 0.99 1.32 * *
MCODER2 0.043 0.097 0.62 0.90 0.92 1.17 1.47 *
The actual code used is listed below. It's possible to Extrapolate what BM1-6 are, because they simply add code to end up with BM7. Bm 8's main loop is listed separately.
Code: REM BM7
FUNCTION t() as uLong
asm
LD DE,(23674)
LD D,0
LD HL,(23672)
end asm
end function
goto start
subroutine:
return
start:
DIM time,i as uInteger
DIM k,var,j as uByte
let time =t()
LET k=5
LET i=0
label:
LET i=i+1
LET var=k/2*3+4-5
gosub subroutine
DIM M(5) as uInteger
FOR j=0 to 4
LET M(j)=i
NEXT j
IF i<1000 then GOTO label: END IF
print (CAST (FLOAT,t())-time)/50
BM 8 replaces most of the code with:
Code: REM BM8
DIM i,j as ubyte
j=2
FOR i=1 to 100
result=j^2
result=ln(j)
result=sin(j)
next i
This is changed from using constants to prevent constant folding optimizations.
RESULTS and DISCUSSION
First up, passing all the benchmarks and more, clearly Boriel's work is by far the most flexible and comprehensive compiler available. It blows the spots off everything else in terms of WHAT it can compile, and all credit to him for creating it. It is excellent!
In terms of performance, it's pretty amazing, too. It's the second fastest of all the compilers listed here. Only ZIP goes faster, generally. BM7 is a little disappointing, in that the produced code seems to be slower than both MCODER 2 and Zip by a quite significant margin. Perhaps some examination of array handling code could improve this. With version 1.25 beta, sadly, I couldn't use -O3 as an option - the programs all failed to compiler with this option enabled, so I couldn't see if peephole optimization would make a difference. It's worth noting that most On Spectrum compilers refused to deal with floating point numbers. In this roundup, only Softek FP could do it, and that barely faster than Basic. Boriel's compiler blew me away with the FP result, frankly. I had to check to see if it was doing it correctly, it was so amazing! There might be some sneaky optimization happening, but printing the numbers as it created them did seem to work fine. (Note: It WAS cheating. It was putting in constants at compile time. A clever option, but not what we were aiming to test. This number has been changed)
Fixed Hisoft Basic Numbers. These corrected numbers do in fact show it produces some of the fastest code available, sometimes beaten by ZIP 1.5. It far outmatches what ZIP can do, however, in that it deals with FP as well as integer - and it seems to do both faster than the competition. Of course ZX BASIC basic excels at being FP and Integer aware as well.
Added in Tobos. It's fully FP, so tends to be slow where integer math could improve things. But look at BM8!
ZX BASIC In short: Solid and well optimized. Seems to be slow in BM7 (array handling). Very clever use of constant insertion to produce good BM8 speed value of 0.1 but now times are corrected because that was cheating a little!
[Edit] - Array handling speed has been dramatically increased with later versions. Boriel has stated that he will be looking into further array optimizations similar to Hisoft Basic methods - so we can hope for another doubling of speed, perhaps! hock:
|
|
|
leer de un archivo txt |
Posted by: omontero - 02-18-2010, 01:50 PM - Forum: Off-Topic
- No Replies
|
|
Saludos amigos,
necesito saber como consultar la informacion de un archivo txt y colocarla en mi sitio drupal en cualquier pagina web, si alguien me puede ayudar se lo agradecere. Drupal se desarrollo con PHO por lo que muchas de las funciones de PHP corren en Drupal.
Saludos a todos y gracias de antemano.
Osbel
|
|
|
read from a txt file |
Posted by: omontero - 02-18-2010, 01:47 PM - Forum: Off-Topic
- Replies (1)
|
|
Hi,
I am developed a web site with drupal, and need some help. I need to read a txt file to view information and then put it in a web page.
Thanks anyway.
bye
|
|
|
Function calls |
Posted by: britlion - 02-17-2010, 01:15 PM - Forum: ZX Basic Compiler
- Replies (3)
|
|
When doing assembler based function calls, there's something that confuses me about the stack.
Code: FUNCTION thing (num1 as uByte, num2 as uByte) as uByte
asm
DI
HALT
end asm
END FUNCTION
When the virtual computer crashes, you can look at the registers and the stack and find out what it's doing.
The stack seems to have
uinteger <something>
uinteger <return address>
uinteger <44,num1>
uinteger <44,num2>
A is set to num1
First question: What's the <something> ? I end up popping it off the stack and dumping it. This worries me.
Second question: If I can trust A to be num1 already, why do I have to go through num1 to get to num2?
Third question: Why the 44's strapped to each byte parameter?
So right now I end up:
Code: POP BC ; throw this away
POP HL ; return address
POP AF ; num 1 -> A
POP DE ; num2 -> D.
And since that's less than helpful:
LD E,D
LD D,0
To make DE the value of num2.
Question 1 worries me most. What IS that extra value on the stack?
Is there a better way of handling parameters - with IX+offset, say?
Does the compiler set it to clean up the stack afterwards, and I shouldn't POP it at all?
Sorry to whine, but this isn't documented, and I'm trying to reverse engineer it! I've got the hang of fastcall, but soemtimes I want more than one parameter.
|
|
|
Memory corruption (Bugs 1.25 Beta) (*solved*) |
Posted by: britlion - 02-16-2010, 01:43 AM - Forum: Bug Reports
- Replies (8)
|
|
* Local array issues:
I noticed that a table I had in a subroutine wasn't returning the correct values. Finally pinned down a short program that demonstrates this:
(Both printed lines should be the same)
Code: SUB failing(a as ubyte,b as ubyte, c as byte, d as byte, text as string)
DIM table2(25) as uByte => {18,24,16,14,14,12,20,12,12,16,14,6,12,10,18,14,26,18,24,8,12,24,12,26,18,10}
print table2(0);" ";table2(1)
end sub
sub working()
DIM table(25) as uByte => {18,24,16,14,14,12,20,12,12,16,14,6,12,10,18,14,26,18,24,8,12,24,12,26,18,10}
print table(0);" ";table(1)
end sub
cls
working()
failing(1,2,3,4,"A")
Interestingly if you swap the order that the two subs are in, which one breaks swaps too - it's the first one defined that breaks each time.
|
|
|
Wishlist |
Posted by: britlion - 02-13-2010, 11:44 AM - Forum: Wishlist
- Replies (8)
|
|
- * Faster Printing routine
* Ability to print anywhere on the 256*192 grid, with optional attributes
* Different sized printing (I'll probably tackle 64 Char printing as well as that 42 character one eventually)
* Interrupt driven routines
* Automated 128K support
*More people adding to function and subroutine libraries
|
|
|
|