Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
A string bug in 1.2.8-s682 (*solved*)
#1
This does not work:

Code:
#Include "alloc.bas"
Declare function String$ (ByVal NumberOfChars as ubyte, ByVal Char as string) as string
Declare sub PlayScrBasic (byval SkyColor as ubyte)

Ink 7: Paper 0: Flash 0: Bright 1: Over 0: Inverse 0: Border 0: Cls
Print "Hello"

Const Black as ubyte = 0
Const Blue as ubyte = 1
Const Red as ubyte = 2
Const Magenta as ubyte = 3
Const Green as ubyte = 4
Const Cyan as ubyte = 5
Const Yellow as ubyte = 6
Const White as ubyte = 7

PlayScrBasic (Cyan)
End


Function String$ (ByVal NumberOfChars as ubyte, ByVal Char as string) as string

'Dim Chars$ as string

'Dim CharPtr as uinteger
'Dim CharsPtr as uinteger
'Dim CharsPtrDeallocate as uinteger
'CharStr
'NumberOfChars = NumberOfChars + 1
'CharsPtr = Allocate(NumberOfChars)
'Dim CharStr as string at @CharP


''CharP = @Char$
'Return "x" '@Char$

Dim i as ubyte

For i = 1 to NumberOfChars
  Chars$ = Chars$ + Char$
Next i

Return Chars$

End Function

sub PlayScrBasic (byval SkyColor as ubyte)

Dim i as ubyte
Dim Space32$ as string
Space32$ = String$(32, " ")

cls
Paper SkyColor
If SkyColor <> 0 then
  fOR i = 0 TO 12
    'Print at i, 0; String$(32, " ")
    Print at i, 0; Space32$
  Next i
End if
Space32$ = ""

Paper Green
Print at 11, 6; String$(21, " ")

FOR i = 8 TO 21
  Paper Red
  Print at i, 5; " "
  IF i > 11 THEN
    Print at i,5; String$(22, " ")
    IF i > 12 AND i < 21 THEN
      Paper Blue
      Print at i, 0; String$(5, " ")
      Print at i, 27; String$(5, " ")
    End if
  End if
Next i

Paper Yellow
Print at 21, 0; String$(5, "Û")
Print at 21, 27; String$(5, "Û")
Paper Black

end sub

However if I rem out everything that has Space32$ in it and unrem:
'Print at i, 0; String$(32, " ")'
Then it works fine and heap size does not seem to matter. If I press break
and restart the program then it fails on the second run even though it
works fine the first time if I make the changes noted above.

My bat file to compile this is as follows:
@echo off
if exist GAME.TAP del GAME.TAP
zxb Invasion.b --optimize=0 --output=GAME --tap --BASIC --autorun --org=39680 --array-base=0 --string-base=0 --heap-size=1280 --strict-bool --enable-break
ren GAME GAME.TAP

I do not trust this string handling and it would be nice to have a inbuildt
String$(NumChars, Char$) function.

Thanks,

Darkstar.
Reply
#2
Thanks for your bug reporting. I will check it this evening.
Also, I notice you #include <alloc.bas> but this is not needed for your code. Maybe you are planning to use it later?
Anyway: I'll check it this evening (have others bugs pending to be fixed) :roll:
Reply
#3
boriel Wrote:Thanks for your bug reporting. I will check it this evening.
Also, I notice you #include <alloc.bas> but this is not needed for your code. Maybe you are planning to use it later?
Anyway: I'll check it this evening (have others bugs pending to be fixed) :roll:
Your welcome. I was planing to use it for later but I have since rem-ed out.
I have also changed the ORG address from 39680 to 40704 and removed
--strict-bool. If I where to use double buffering then the second screen would
sit in uncontended memory for speed at address 32768 to 39679 and then
there is 1KiB for the stack and that brings us to address 40704. Then there
is 23KiB for program and data followed by 1280 (1.25 KiB) for the heap and
that brings the address up to 65536 or fully used memory except for 8KiBs
of lower contended memory that is not used. That get's me to my point.
It would be good if I could place non speed critical sections of my program
below the ORG address for e.x.: Sub Foo at Low....End sub. Then low would
be a #Define. For this case, Low would be 32767 then the compiler would
compile a Sub or a Function, get the complied length of it and do a Low -
Length and place it at that address and then update (decrement) Low
accordingly and so on until all the Subs and Functions that were marked
with "at Low" are compiled.

Also, if I specify the output file as GAME.TAP then GAME.TAP shows up
in the byte header instead of stripping the extension out causing me to
do a rename from the .BAT file. What was the option (--) for the ROM
print routines and has it be taken out? If so why? Last it would be nice to
have a PutChar (8x8 pixels) at graphics coordinates in the library, clipping
supported for the edges of the screen and Attr supported and a routine with
Attr support stripped out of it.

I do not think string slicing works as supposed but I have not checked it
since 1.2.6 and that's it for now.

I do hope that you find out what the problem is because this is unusable.

Thanks you,

Darkstar.
Reply
#4
I forgot, in the Low section the strings and variables would be placed
there for the routines compiled with Low leaving only the heap as a common
data area for both sections of the program and a low limit could be 24KiB.

I did rewrite the code I posted above for speed, it uses direct POKEing into
the ATTR section of the display file instead of the String$ method.

Darkstar.
Reply
#5
Darkstar Wrote:Last it would be nice to
have a PutChar (8x8 pixels) at graphics coordinates in the library, clipping
supported for the edges of the screen and Attr supported and a routine with
Attr support stripped out of it.

Darkstar.

Please look here: <!-- l --><a class="postlink-local" href="http://www.boriel.com/forum/how-to-tutorials/topic468.html">how-to-tutorials/topic468.html</a><!-- l -->

And I think you might mean this: <!-- m --><a class="postlink" href="http://www.boriel.com/wiki/en/index.php/ZX_BASIC:HRprint.bas">http://www.boriel.com/wiki/en/index.php ... Rprint.bas</a><!-- m -->

Note there's quite a few snippets of code in the wiki library. I've been adding a lot of stuff of mine there.
Reply
#6
britlion Wrote:
Darkstar Wrote:Last it would be nice to
have a PutChar (8x8 pixels) at graphics coordinates in the library, clipping
supported for the edges of the screen and Attr supported and a routine with
Attr support stripped out of it.

Darkstar.

Please look here: <!-- l --><a class="postlink-local" href="http://www.boriel.com/forum/how-to-tutorials/topic468.html">how-to-tutorials/topic468.html</a><!-- l -->

And I think you might mean this: <!-- m --><a class="postlink" href="http://www.boriel.com/wiki/en/index.php/ZX_BASIC:HRprint.bas">http://www.boriel.com/wiki/en/index.php ... Rprint.bas</a><!-- m -->

Note there's quite a few snippets of code in the wiki library. I've been adding a lot of stuff of mine there.

Thank you. The HRPrint was something I was looking for, 1x1 or 8x8 pixels.
I can use this although it does not support clipping and the attr support
I can strip out myself if I want to. This comes in handy. Plus your routine.
Reply
#7
Darkstar Wrote:
britlion Wrote:
Darkstar Wrote:Last it would be nice to
have a PutChar (8x8 pixels) at graphics coordinates in the library, clipping
supported for the edges of the screen and Attr supported and a routine with
Attr support stripped out of it.

Darkstar.

Please look here: <!-- l --><a class="postlink-local" href="http://www.boriel.com/forum/how-to-tutorials/topic468.html">how-to-tutorials/topic468.html</a><!-- l -->

And I think you might mean this: <!-- m --><a class="postlink" href="http://www.boriel.com/wiki/en/index.php/ZX_BASIC:HRprint.bas">http://www.boriel.com/wiki/en/index.php ... Rprint.bas</a><!-- m -->

Note there's quite a few snippets of code in the wiki library. I've been adding a lot of stuff of mine there.

Thank you. The HRPrint was something I was looking for, 1x1 or 8x8 pixels.
I can use this although it does not support clipping and the attr support
I can strip out myself if I want to. This comes in handy. Plus your routine.
Please discuss this in the wishlist (or the whatever ?? :mrgreen: ) subforum. From time to time people goes there and suggest changes or put code snippets and sometimes I bundle some of them with the compiler. The idea is it should be very generic (not purpose specific) routines.
Reply
#8
Okay: The bug seems to be (finally!) fixed. It's been a very tough one :x
It happened when ADDing initialized (NULL) strings (if you had initalized Char$ = "" in your function the bug). NULL (uninitialized) strings are allowed by the compiler and managed as empty ones. :roll: So:
Code:
A$ = A$ + "5"
PRINT A$
Should print just 5. The problem was the STRADD routine had a bug for this case. :roll: Now fixed.

Also, #include <alloc.bas> had a bug of bad included (also fixed), and now contains 2 new important functions:
  • Memavail() .- Returns the total available (and maybe fragmented) free Heap Memory. Notice that if there are 1Kb of free memory it can be a single contiguous block or, for example, 4 chunks of 256 bytes (in such case you can only get at most 256 bytes when calling allocate() ).
  • MaxAvail() .- Returns the size (in bytes) of the largest continuous available/free memory block in the Heap. Calling Allocate(N) with N greater than the value returned by this function will result in a memory error (NULL returned or Out Of Memory error if --check-memory is enabled).
Please, download 1.2.8s696 here, test your program and tell me.
Reply
#9
boriel Wrote:Okay: The bug seems to be (finally!) fixed. It's been a very tough one :x

Please, download 1.2.8s696 here, test your program and tell me.

Sorry for the late reply, I was busy with my girlfriend.

I kinda knew that this would be a tough one and it's very good to have those
two extra functions to keep an overview of the heap. The fix works OK for
the routine posted above so that is a big relief thank you very much. Break
works OK also. Can you compact the heap? You could do that in QuickBasic.

Thanks,

Darkstar
Reply
#10
Darkstar Wrote:
boriel Wrote:Okay: The bug seems to be (finally!) fixed. It's been a very tough one :x

Please, download 1.2.8s696 here, test your program and tell me.

Sorry for the late reply, I was busy with my girlfriend.

I kinda knew that this would be a tough one and it's very good to have those
two extra functions to keep an overview of the heap. The fix works OK for
the routine posted above so that is a big relief thank you very much. Break
works OK also. Can you compact the heap? You could do that in QuickBasic.

Thanks,

Darkstar
The heap es automatically defragmented on each free operation, if possible. Compacted means all blocks must be moved down, the free-list updated and compacted and also locate each declared string var (ponter) in memory and update it accordingly. The problem is: this is an expensive (time/space) function for the speccy, must be done dynamically and you will probably end wasting more space compiling that function that the memory you want to free in a 48Kb system. :|
Reply
#11
boriel Wrote:The heap es automatically defragmented on each free operation, if possible. Compacted means all blocks must be moved down, the free-list updated and compacted and also locate each declared string var (ponter) in memory and update it accordingly. The problem is: this is an expensive (time/space) function for the speccy, must be done dynamically and you will probably end wasting more space compiling that function that the memory you want to free in a 48Kb system. :|
QuickBasic did it's own garbage collection but you could force it if needed.
Defragmentation and compacting goes hand in hand as I understand it. If the
compiler does it's own defragmentation/compacting upon each free operation
then it would not be so big of a deal to make that avialible to the ZX BASIC
programer provided that it's modular enough. This is always an expensive
operation in computing and thus you can force it under idle circumstances.
Reply
#12
Darkstar Wrote:
boriel Wrote:The heap es automatically defragmented on each free operation, if possible. Compacted means all blocks must be moved down, the free-list updated and compacted and also locate each declared string var (ponter) in memory and update it accordingly. The problem is: this is an expensive (time/space) function for the speccy, must be done dynamically and you will probably end wasting more space compiling that function that the memory you want to free in a 48Kb system. :|
QuickBasic did it's own garbage collection but you could force it if needed.
Defragmentation and compacting goes hand in hand as I understand it. If the
compiler does it's own defragmentation/compacting upon each free operation
then it would not be so big of a deal to make that avialible to the ZX BASIC
programer provided that it's modular enough. This is always an expensive
operation in computing and thus you can force it under idle circumstances.
Not exactly. I implemented a heap (usually used in legacy C/Pascal compilers) which only gives memory blocks and maintain a linked list of free ones. This is a very common heap, specially indicated for systems with little memory or embedded systems, etc. A Garbage collector might need much more metadata to be maintained, and variables also need to be referenced (probably with a ref counter, etc). This is implementation is pretty straight (faster and lighter). There are some optimizations that can be done. E.g. A$ = A$ + B$ could be detected and compiled as A$ += B$; (+= operator is not supported). Which could be compiled as a REALLOC followed by a concatenation. REALLOC routine is implemented, and reduces fragmentation.
Reply
#13
boriel Wrote:REALLOC routine is implemented, and reduces fragmentation.
Then if you want to compact it then there is no real way to do that. Is there
a way to do that without having all that metadata around? If you got a big
program that works with text then compacting may be needed or give the
program a very large heap and even that can eventually run out without
compacting.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)