Fun with CBM arithmetics
Moderator: Moderators
- Mike
- Herr VC
- Posts: 4842
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Proposal for a patch
Here's my proposal for a patch:
1. It is intended to keep the optimization,
2. It must be ensured, that the routine at $D983 is always called with C=1,
3. It must be ensured, that the contents of $68 are 0 upon calling $D983.
The routine in question is buried (too) deep into the BASIC ROM, and it is not vectored.
A patch will require the replacement of the BASIC ROM.
4. DA5B JMP $D983 needs to be rerouted to a suitably 'empty' place within $C000 .. $DFFF,
5. one possible candidate might be the range $DF53 .. $DF70:
The addresses $DF53 .. $DF70 contain only $AA's and are located after two tables, which contain powers of 10 and TI conversion constants, but the conversion loop beginning at $DE66 (spanning to $DEC2) stops at Y=$24 or Y=$3C and never reaches into $DF53 .. $DF70. There are also no other references in the BASIC ROM to that address range.
[...]
Edit: I replaced the original version of the patch with a revised one (download). For the source, see a few posts further down this topic.
1. It is intended to keep the optimization,
2. It must be ensured, that the routine at $D983 is always called with C=1,
3. It must be ensured, that the contents of $68 are 0 upon calling $D983.
The routine in question is buried (too) deep into the BASIC ROM, and it is not vectored.
A patch will require the replacement of the BASIC ROM.
4. DA5B JMP $D983 needs to be rerouted to a suitably 'empty' place within $C000 .. $DFFF,
5. one possible candidate might be the range $DF53 .. $DF70:
The addresses $DF53 .. $DF70 contain only $AA's and are located after two tables, which contain powers of 10 and TI conversion constants, but the conversion loop beginning at $DE66 (spanning to $DEC2) stops at Y=$24 or Y=$3C and never reaches into $DF53 .. $DF70. There are also no other references in the BASIC ROM to that address range.
[...]
Edit: I replaced the original version of the patch with a revised one (download). For the source, see a few posts further down this topic.
Last edited by Mike on Thu Feb 20, 2014 5:10 pm, edited 2 times in total.
- orion70
- VICtalian
- Posts: 4341
- Joined: Thu Feb 02, 2006 4:45 am
- Location: Piacenza, Italy
- Occupation: Biologist
Re: Fun with CBM arithmetics
Congrats on being the first to release software in 2014
- Mike
- Herr VC
- Posts: 4842
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Fun with CBM arithmetics
PM sent.orion70 wrote:Congrats on being the first to release software in 2014
- Kweepa
- Vic 20 Scientist
- Posts: 1315
- Joined: Fri Jan 04, 2008 5:11 pm
- Location: Austin, Texas
- Occupation: Game maker
Re: Fun with CBM arithmetics
Checked out the other emulators in VICE.
BASIC 2, 3.5 and 4 suffer from this bug, but it's absent in BASIC 7.
BASIC 2, 3.5 and 4 suffer from this bug, but it's absent in BASIC 7.
- Mike
- Herr VC
- Posts: 4842
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Fun with CBM arithmetics
In the last two days I checked the patched BASIC ROM in two installations of VICE on my notebook.
As a picture is more worth than a thousand words, I got the idea to use my Mandelbrot zoomer for illustrating purposes:
Here's a co-ordinate set, where both x- and y-coordinates just straddle across a critical interval:
Now for the results, with the original ROM to the left (download) and with the patched ROM to the right (download):
Parts of the left picture are distorted and torn, compared to the right picture.
Here's the same co-ordinate set computed on the PC, same display algorithm, just higher resolution:
Edit: refined example
As a picture is more worth than a thousand words, I got the idea to use my Mandelbrot zoomer for illustrating purposes:
Here's a co-ordinate set, where both x- and y-coordinates just straddle across a critical interval:
Code: Select all
x_min = -0.531250128
x_max = -0.531249872
y_min = 0.531249904
y_max = 0.531250096
1024 Iterations
Parts of the left picture are distorted and torn, compared to the right picture.
Here's the same co-ordinate set computed on the PC, same display algorithm, just higher resolution:
Edit: refined example
Last edited by Mike on Thu Feb 20, 2014 5:11 pm, edited 1 time in total.
Re: Fun with CBM arithmetics
Nice work Mike! Thanks.
The VIC and the C64 have almost exactly the same BASIC ROM just located in different memory ranges.
VIC - C000-DFFF
C64 - A000-BFFF
Here's the same patch modified for the C64.Kweepa wrote:Nice find!
The same bug is of course in the c64...
Code: Select all
10 open2,8,2,"basic,s,r"
11 open3,8,3,"basic-p,s,w"
12 fort=40960to49151
13 get#2,a$:a=asc(a$+chr$(0))
14 ift=47708thena= 83:goto22
15 ift=47709thena=191:goto22
16 ift=48979thena=133:goto22
17 ift=48980thena=104:goto22
18 ift=48981thena= 56:goto22
19 ift=48982thena= 76:goto22
20 ift=48983thena=131:goto22
21 ift=48984thena=185
22 print#3,chr$(a);
23 next
24 close3
25 close2
VIC - C000-DFFF
C64 - A000-BFFF
Ray..
- Mike
- Herr VC
- Posts: 4842
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Fun with CBM arithmetics
On the C64, it is also possible to copy the BASIC-ROM into the RAM, and patch it there. Here's a program which does exactly this:
Here's a revised version of the patch, which installs an own routine to handle the mantissa in the free range of $DF53 .. $DF70, and does not anymore 're-use' the normalize routine. Even if it now uses up some more bytes of that free space, it is now implemented as it should have been done in the first place. The jump at $DA5B now is altered to:
... and the routine at $DF5A now is:
This is, what the original shortcut at $D983 was supposed to do, only that one fails under those circumstances I already described in the earlier postings. The following program applies the new patch to a *.bin file of the BASIC ROM:
I also found some interesting reference about those early implementations of Microsoft BASIC on the 65xx. The owner of the blog reconstructed one single source code repository for CBM BASIC V1, OSI BASIC, AppleSoft I, KIM-1 BASIC, CBM BASIC V2 (PET), Intellivision Keyboard Component BASIC and MicroTAN BASIC ... and with the exception of OSI BASIC (it only uses a 3-byte mantissa, thus the error can't happen there) all share that bug in the multiplication routine ...!
Even *more* interesting is, that they somehow came to the same conclusions about the carry flag as I did, but they were not quite sure about how to handle it. In the BASIC ROM, the routine is located at $8A55:
... with $8962 again being the short-cut. At $8A57, they had possibly put a SEC before - and then decided to go the save route by disabling the optimization instead (only in one of five cases, the routine is still called over $8A55, all other 4 calls enter at $8A5B). Anyway they had more than enough space in the ROM to do it right, but alas.
Code: Select all
1 POKE1,PEEK(1)AND248OR7
2 FORT=40960TO53247:POKET,PEEK(T):NEXT
3 POKE47708,83:POKE47709,191
4 FORT=0TO5:READA:POKE48979+T,A:NEXT
5 POKE1,PEEK(1)AND248OR6
6 DATA133,104,56,76,131,185
Code: Select all
.DA5B 4C 5A DF JMP $DF5A
Code: Select all
.DF5A A5 29 LDA $29
.DF5C 85 70 STA $70
.DF5E A5 28 LDA $28
.DF60 85 29 STA $29
.DF62 A5 27 LDA $27
.DF64 85 28 STA $28
.DF66 A5 26 LDA $26
.DF68 85 27 STA $27
.DF6A A0 01 LDY #$01
.DF6C 98 TYA
.DF6D 4A LSR A
.DF6E 85 26 STA $26
.DF70 60 RTS
Code: Select all
10 OPEN2,8,2,"BASIC,S,R"
11 OPEN3,8,3,"BASIC-P,S,W"
12 READB,C,D
13 FORT=49152TO57343
14 GET#2,A$:A=ASC(A$+CHR$(0))
15 IFB<>TTHEN18
16 IFA<>CTHENPRINT"BAD SOURCE FILE!":GOTO20
17 A=D:READB,C,D
18 PRINT#3,CHR$(A);
19 NEXT
20 CLOSE3
21 CLOSE2
22 :
23 DATA 55900,131, 90
24 DATA 55901,217,223
25 DATA 57178,170,165
26 DATA 57179,170, 41
27 DATA 57180,170,133
28 DATA 57181,170,112
29 DATA 57182,170,165
30 DATA 57183,170, 40
31 DATA 57184,170,133
32 DATA 57185,170, 41
33 DATA 57186,170,165
34 DATA 57187,170, 39
35 DATA 57188,170,133
36 DATA 57189,170, 40
37 DATA 57190,170,165
38 DATA 57191,170, 38
39 DATA 57192,170,133
40 DATA 57193,170, 39
41 DATA 57194,170,160
42 DATA 57195,170, 1
43 DATA 57196,170,152
44 DATA 57197,170, 74
45 DATA 57198,170,133
46 DATA 57199,170, 38
47 DATA 57200,170, 96
48 DATA -1, -1, -1
Yes, I saw that, too. The bug is absent in V7, because Commodore effectively disabled the optimization that caused it. Of course, that means that multiplication now is generally slower on the C128.Kweepa wrote:Checked out the other emulators in VICE.
BASIC 2, 3.5 and 4 suffer from this bug, but it's absent in BASIC 7.
Even *more* interesting is, that they somehow came to the same conclusions about the carry flag as I did, but they were not quite sure about how to handle it. In the BASIC ROM, the routine is located at $8A55:
Code: Select all
.8A55 D0 04 BNE $8A5B
.8A57 EA NOP
.8A58 4C 62 89 JMP $8962
.8A5B [...]
- Mike
- Herr VC
- Posts: 4842
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Fun with CBM arithmetics
In case you've been wondering what became of this, look here.Mike wrote:A patch will require the replacement of the BASIC ROM.
Re: Fun with CBM arithmetics
I am hoping to get this patch (and others) into the SuperVixen. It will be in a copy of Basic in the external cartridge, so not a replacement ROM, but patched during copy to external RAM.
I am wondering if anyone has a list of such patches? I am thinking about a file format to get them loaded and patched during boot, so that anyone finding such problems in the future, will also be able to add their own patch.
What do you think about it?
I am wondering if anyone has a list of such patches? I am thinking about a file format to get them loaded and patched during boot, so that anyone finding such problems in the future, will also be able to add their own patch.
What do you think about it?
Last edited by Kakemoms on Sat Feb 17, 2018 6:01 pm, edited 1 time in total.
- Mike
- Herr VC
- Posts: 4842
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Fun with CBM arithmetics
Regards your question of a feasible file format: you'd most probably be content with a *.prg file that executes the patch by copying the original ROM contents, doing a check whether it works on the original byte values it aims to replace, and putting the replacement bytes there. Much similar to how I proceeded with the file based patch here.
There are other known bugs in the CBM BASIC interpreter, but they are mostly irrelevant or easy to avoid: broken type checks lead to overflow of the string stack in the IF ... THEN clause and POS() function with bogus string arguments, or to crashes as with the statement PRINT 5+"A"+-5 ... then there is also a bug in the line number parse routine, which results in a warm start or crash upon entering a certain range of (invalid!) line numbers. In other cases, it is rather easy to improve the BASIC interpreter by means of a BASIC extension/wedge or USR() function - if you count the slowness of the SQR() function as "bug".
As I wrote earlier in the thread, the multiplication routine is buried too deep in the interpreter, and it is not vectored. A soft replacement would require a duplication of a good deal of ROM code of the expression parser down to the multiplication routine itself, and that fixed shortcut routine. We are talking about way more than 1K code here. And it also only helps BASIC programs: machine code programs that happen to use the arithmetic routines of the interpreter have no other choice than to call the multiply routine in the BASIC ROM directly - exactly because there is no vector pointing there - and thus will be in the dark about a soft loaded fix!
Those are the reasons I made a real job of replacing the BASIC ROM. The other alternative that came to my mind, supplying RAM under ROM, was more like taking a sledgehammer to crack a nut - at least for that single fix.
From what I know, this is probably the first - and thus far only one - direct patch of the VIC-20 BASIC ROM.Kakemoms wrote:I am wondering if anyone ha[s] a list of such patches?
There are other known bugs in the CBM BASIC interpreter, but they are mostly irrelevant or easy to avoid: broken type checks lead to overflow of the string stack in the IF ... THEN clause and POS() function with bogus string arguments, or to crashes as with the statement PRINT 5+"A"+-5 ... then there is also a bug in the line number parse routine, which results in a warm start or crash upon entering a certain range of (invalid!) line numbers. In other cases, it is rather easy to improve the BASIC interpreter by means of a BASIC extension/wedge or USR() function - if you count the slowness of the SQR() function as "bug".
As I wrote earlier in the thread, the multiplication routine is buried too deep in the interpreter, and it is not vectored. A soft replacement would require a duplication of a good deal of ROM code of the expression parser down to the multiplication routine itself, and that fixed shortcut routine. We are talking about way more than 1K code here. And it also only helps BASIC programs: machine code programs that happen to use the arithmetic routines of the interpreter have no other choice than to call the multiply routine in the BASIC ROM directly - exactly because there is no vector pointing there - and thus will be in the dark about a soft loaded fix!
Those are the reasons I made a real job of replacing the BASIC ROM. The other alternative that came to my mind, supplying RAM under ROM, was more like taking a sledgehammer to crack a nut - at least for that single fix.
Re: Fun with CBM arithmetics
Well, there is no way to get the 65C02 to see the internal ROM, so it will have to be in RAM anyway. Thus a patch is straightforward..Mike wrote:Those are the reasons I made a real job of replacing the BASIC ROM. The other alternative that came to my mind, supplying RAM under ROM, was more like taking a sledgehammer to crack a nut - at least for that single fix.
-
- Vic 20 Afficionado
- Posts: 348
- Joined: Tue Apr 14, 2009 8:15 am
- Website: http://wimbasic.webs.com
- Location: Netherlands
- Occupation: farmer
Re: Adding 0.1 + 0.2 in CBM float
Mike,
This is just to let you know about this test I did.
I have now used your most recent patch on the Basic image. Starting VICE gives: "VIC20MEM: Error - Warning: Unknown Basic image. Sum: 31364 ($7A84)."
Reverting to the original Basic image:
Regards,
Wim.
This is just to let you know about this test I did.
I have now used your most recent patch on the Basic image. Starting VICE gives: "VIC20MEM: Error - Warning: Unknown Basic image. Sum: 31364 ($7A84)."
Reverting to the original Basic image:
Regards,
Wim.
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
- Mike
- Herr VC
- Posts: 4842
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Adding 0.1 + 0.2 in CBM float
Hi, wimoos,
The patched BASIC calculates 16^(log(3)/log(2)) as just a little bit smaller than 81. Upon output with PRINT, that value is rounded up and prints as 81, but INT() (or the assignment to an integer variable) rounds down to 80. When you calculate A=-16^P (note the sign-inversion!), W%=A for the patched BASIC yields -81 and the original BASIC will result in -82, so there ...
Greetings,
Michael
I suppose this counts as expected behaviour. It *is* an unknown BASIC ROM image as far as VICE is concerned.wimoos wrote:This is just to let you know about this test I did.
I have now used your most recent patch on the Basic image. Starting VICE gives: "VIC20MEM: Error - Warning: Unknown Basic image. Sum: 31364 ($7A84)."
[...]
Now, if you do slightly more complex calculations with non-integer numbers (log(3)/log(2) = 1.5849625...) in the presence of rounding errors and implementation details of a given floating point system to ultimately try to construct integer numbers (+/- 1 or 2 ULP) - and then apply the INT() function (which is implicit here in the assignment to an integer variable) ... you just get those kind of results. Again, this is expected behaviour.[...]
Reverting to the original Basic image:Code: Select all
P=LOG(3)/LOG(2) A=16^P PRINT A (... prints 81) W%=A PRINT W% (... prints 80)
Code: Select all
P=LOG(3)/LOG(2) A=16^P PRINT A (... prints 81.0000001) W%=A PRINT W% (... prints 81)
The patched BASIC calculates 16^(log(3)/log(2)) as just a little bit smaller than 81. Upon output with PRINT, that value is rounded up and prints as 81, but INT() (or the assignment to an integer variable) rounds down to 80. When you calculate A=-16^P (note the sign-inversion!), W%=A for the patched BASIC yields -81 and the original BASIC will result in -82, so there ...
Greetings,
Michael
- MrSterlingBS
- Vic 20 Enthusiast
- Posts: 174
- Joined: Tue Jan 31, 2023 2:56 am
- Location: Germany,Braunschweig
Re: Fun with CBM arithmetics
I am playing with the NEW BASIC ROM and MG extension and found that the NEW BASIC ROM is about 0.8% faster than the OLD one!
- Attachments
-
- milkiway.zip
- (195 Bytes) Downloaded 35 times
Last edited by Mike on Wed Aug 23, 2023 5:54 am, edited 1 time in total.