Tuesday, January 17, 2023

A quick port of a running cat animation

0 POKE65497,0:PMODE4,1:PCLS
10 SCREEN 1:CLS:DIM A(1,36),B(1,36),C(1,36),D(1,36),E(1,36),F(1,36):FOR I=1 TO 6:READ G(I):NEXT I
20 COLOR1:FOR I=1 TO 6:FOR J=1 TO 13:READ A$:FOR K=10 TO 41:IF MID$(A$,K-9,1)="1"THEN PSET(K,J)
30 NEXT K:NEXT J:ON I GOSUB 40,50,60,70,80,90:PCLS:NEXT I:GOTO 890
40 GET(1,1)-(41,13),A:RETURN
50 GET(1,1)-(41,13),B:RETURN
60 GET(1,1)-(41,13),C:RETURN
70 GET(1,1)-(41,13),D:RETURN
80 GET(1,1)-(41,13),E:RETURN
90 GET(1,1)-(41,13),F:RETURN
100 DATA 8,5,9,6,5,7
110 DATA 00000000000000000000000000000000
120 DATA 00000000000000000000000000000000
130 DATA 00000000000000000000001111111010
140 DATA 00000000000111111111110000000110
150 DATA 00000000111000000000000000000001
160 DATA 00000001000000000000000100111001
170 DATA 00000110000000000000000100100110
180 DATA 01111100000000111111111110110000
190 DATA 10001000011111000000000001111100
200 DATA 00001111100000000000000000001010
210 DATA 00011000000000000000000000000101
220 DATA 00101000000000000000000000000000
230 DATA 00001100000000000000000000000000
240 DATA 00000000000000000000000000000000
250 DATA 00000000000000000000000000000000
260 DATA 00000000000000000000000000000000
270 DATA 00000000001111111000011111000100
280 DATA 00000000110000000111100000111100
290 DATA 00000001000000000000000000000010
300 DATA 00000110000000000000000101110001
310 DATA 11111010000001111111111111001110
320 DATA 00000110001110000000001101110000
330 DATA 00011101110000000000000100011100
340 DATA 00001000000000000000000100000011
350 DATA 00110000000000000000000110000000
360 DATA 00000000000000000000000011000000
370 DATA 00000000000000000000000000000000
380 DATA 00000000000001111100000000000000
390 DATA 00000000000110000011000000001000
400 DATA 00000000011000000000111110111100
410 DATA 00000000110000000000000001000010
420 DATA 00000001001000001000000000010001
430 DATA 00000010001000010110000000101110
440 DATA 01111100010000100001111101000000
450 DATA 00000000010111000000010101000000
460 DATA 00000000001000000001100011100000
470 DATA 00000000000100000001000000110000
480 DATA 00000000001000000001000000001000
490 DATA 00000000000000000000100000000100
500 DATA 00000000000000000000000000000000
510 DATA 00000000000000111100000000000000
520 DATA 00000000000010000011000000000000
530 DATA 00000011111100000000110000001000
540 DATA 00000100000100000000001000011000
550 DATA 00011000000100100000000111100100
560 DATA 11100000000010010001000000000010
570 DATA 00000000000001011010000000111100
580 DATA 00000000000000110110111111000000
590 DATA 00000000000000110101100000000000
600 DATA 00000000000000011101100000000000
610 DATA 00000000000000001000100000000000
620 DATA 00000000000000000000110000000000
630 DATA 00000000000000000000000000000000
640 DATA 00000000000000000000000000000000
650 DATA 00111111000011111000000000000000
660 DATA 01000000111100000110000000100000
670 DATA 01000000000100000001100011100000
680 DATA 00000000001000000000011100010000
690 DATA 00000000001000000000000000001000
700 DATA 00000000001000000010000011110000
710 DATA 00000000000101111111101100000000
720 DATA 00000000000110000001010000000000
730 DATA 00000000000101000010100000000000
740 DATA 00000000001101000100000000000000
750 DATA 00000000000110110000000000000000
760 DATA 01110000000000000000000000000000
770 DATA 00001111000000000000000000000000
780 DATA 00000000111000111100000000000100
790 DATA 00000000000111000011000000011110
800 DATA 00000000001000000000111011100001
810 DATA 00000000010000000000000100000001
820 DATA 00000000010000000000000000011110
830 DATA 00000000010000111000000000100000
840 DATA 00000000100001000111111111010000
850 DATA 00000001001110000000000001110000
860 DATA 00000001010000000000000000000000
870 DATA 00000000101000000000000000000000
880 DATA 00000000011110000000000000000000
890 LINE(215,0)-(255,12),PRESET,BF:LINE(0,13)-(255,13),PSET:C=0:I=0
900 C=C+G(I):IF C>215 THEN 890
910 I=I+1:IF I=7 THEN I=1
920 ON I GOSUB 930,940,950,960,970,980:FOR J=1 TO 20:NEXT J:GOTO 900
930 PUT(C,0)-(C+40,12),A:RETURN
940 PUT(C,0)-(C+40,12),B:RETURN
950 PUT(C,0)-(C+40,12),C:RETURN
960 PUT(C,0)-(C+40,12),D:RETURN
970 PUT(C,0)-(C+40,12),E:RETURN
980 PUT(C,0)-(C+40,12),F:RETURN

Friday, November 11, 2022

Tandy CoCo ROM to RAM BASIC program, and disassembly

Here is the Tandy CoCo "ROM to RAM" program that was published back in the 1980s.
It copies the contents of the ROMs to the bank of RAM that can replace it.
Executing the address it's POKEd to will start running BASIC out of RAM.
I hand disassembled it, and commented the disassembly by looking up the opcodes in a book.  I tried using the debugger in VCC, but it doesn't have a disassembler, and my internet was down so I couldn't download something else.

The BASIC and disassembly are included below.  The BASIC program should should still work if you leave out lines 50, 60, and 70, but it will run a little slower.

BASIC:

REM MOVE ROM TO RAM ON A COCO 1 & 2
10 READ A$:IF A$="X" THEN END
20 POKE 20000+N,VAL("&H"+A$)
30 N=N+1:GOTO 10
40 DATA 34,01,1A,50,10,8E,80,00

REM LOOP TO COPY 6 BYTES AT A TIME. FASTER BUT NOT REQUIRED TO WORK
50 DATA B7,FF,DE,EC,A4,AE,22,EE
60 DATA 24,B7,FF,DF,ED,A1,AF,A1
70 DATA EF,A1,10,8C,F3,FC,25,E8

REM LOOP TO COPY 2 BYTES AT A TIME.
80 DATA 10,8C,FF,00,24,0C,B7,FF
90 DATA DE,EC,A4,B7,FF,DF,ED,A1
100 DATA 20,EE,35,01,39
110 DATA X


Assembly:

;*************************************************
;* Tandy CoCo 1 & 2 ROM to RAM
;* copies the contents of ROM to RAM and continues running it from there
;*************************************************

; start at location 20000 (code is position independant though)
            org        $4E20

; start    of code
34,01        pshs    $01            ; save cc register
1A,50        orcc    $50            ; disable interrupts

10,8E,80,00    ldy        $8000        ; point to ROM start address

loop1:                            ; copy 6 bytes at a time
B7,FF,DE    sta        $FFDE        ; set ROM mode
EC,A4        ldd        ,y            ; read 6 bytes of ROM data
AE,22        ldx        2,y
EE,24        ldu        4,y
B7,FF,DF    sta        #$FFDF        ; set RAM mode
ED,A1        std        ,y++        ; write 6 bytes and update mem pointer
AF,A1        stx        ,y++
EF,A1        stu        ,y++
10,8C,F3,FC    cmpy    $F3FC        ; are we done with 6 byte copy?
25,E8        blo        loop1        ; go again if not

loop2:                            ; copy 2 bytes at a time
10,8C,FF,00    cmpy    $FF00        ; are we done with 2 byte copy?
24,0C        bhs        exit        ; branch if yes
B7,FF,DE    sta        $FFDE        ; set ROM mode   
EC,A4        ldd        ,y            ; read 2 bytes
B7,FF,DF    sta        $FFDF        ; set RAM mode
ED,A1        std        ,y++        ; write 2 bytes and update mem pointer
20,EE        bra        loop2        ; loop

exit:
35,01        puls    $01            ; restore cc register
39            rts
 

Saturday, November 5, 2022

BASIC ASCII Mandelbrot Benchmark

This is a CoCo 3 version of the ASCII Mandelbrot Benchmark posted here:
https://github.com/scruss/bench64

This just adds the math patch, 6309 control, and CoCo timing code.
Runs in 12.43 minutes.  Takes over 23 minutes on a C64 according to the comment on that site.


 
0 TIMER=0:POKE 65497,0:WIDTH80

REM GET BASIC TOPRAM POINTER, SUBTRACT SIZE OF USER CODE
1 AD=PEEK(116)*256+PEEK(117)-24

REM RESERVE MEMORY FOR USR CODE
2 CLEAR 100,AD

REM VARIABLES ERASED BY CLEAR, SO REDO AD, POKE USR CODE INTO RAM
3 AD=PEEK(116)*256+PEEK(117):FOR I=0 TO 23:READ B$:A=VAL("&H"+B$):POKE AD+I,A:NEXT

REM DEFINE USR ROUTINES
4 DEFUSR0=AD:DEFUSR1=AD+12

REM ENABLE 6309 NATIVE MODE
5 A=USR0(0)

REM INSTALL HARDWARE MULTIPLY PATCH
6 GOSUB 10000



  100 REM A BASIC, ASCII MANDELBROT
  110 REM
  120 REM This implementation copyright (c) 2019, Gordon Henderson
  130 REM
  140 REM Permission to use/abuse anywhere for any purpose granted, but
  150 REM it comes with no warranty whatsoever. Good luck!
  160 REM
  170 C$ = ".,'~=+:;[/<&?oxOX# " : REM 'Pallet' Lightest to darkest...
  180 SO = 1 : REM Set to 0 if your MID$() indexes from 0.
  190 MI = LEN(C$)
  200 MX = 4
  210 LS = -2.0
  220 TP = 1.25
  230 XS = 2.5
  240 YS = -2.5
  250 W = 64
  260 H = 48
  270 SX = XS / W
  280 SY = YS / H
  290 Q = TIME
  300 FOR Y = 0 TO H
  310   CY = Y * SY + TP
  320   FOR X = 0 TO W
  330     CX = X * SX + LS
  340     ZX = 0
  350     ZY = 0
  360     CC = SO
  370     X2 = ZX * ZX
  380     Y2 = ZY * ZY
  390     IF CC > MI THEN GOTO 460
  400     IF (X2 + Y2) > MX THEN GOTO 460
  410     T = X2 - Y2 + CX
  420     ZY = 2 * ZX * ZY + CY
  430     ZX = T
  440     CC = CC + 1
  450     GOTO 370
  460     PRINT MID$(C$, CC - SO, 1);
  470   NEXT
  480   PRINT
  490 NEXT
  500 PRINT

510 PRINT "TIMER=";TIMER/60

REM DISABLE 6309 NATIVE MODE
530 A=USR1(0)
540 END


REM USR functions to enable/disable 6309 native mode
9000 DATA CC,FF,FF,10,4F,5D,26,03,11,3D,01,39,CC,FF,FF,10,4F,5D,26,03,11,3D,00,39

REM COCO3 HARDWARE MULTIPLY PATCH.
REM JUST ADD A GOSUB 10000 AT THE TOP OF YOUR CODE TO ADD IT

REM ADDRESS WE ARE STORING THE MULTIPLY PATCH IN RAM
10000 AD=VAL("&HFA0C")

REM POKE THE MULTIPLY PATCH INTO RAM.
10001 FORI=0 TO 64:READ B$:A=VAL("&H"+B$):POKE AD+I,A:NEXT

REM MAKE BASIC JUMP TO OUR MULTIPY INSTEAD OF USING IT'S CODE. $BB00 JMP $FA0C
10002 POKE VAL("&HBB02"),VAL("&H7E"):POKE VAL("&HBB03"),VAL("&HFA"):POKE VAL("&HBB04"),VAL("&H0C")

10003 RETURN

10005 DATA 32,79,E7,60,96,60,3D,ED,63,E6,60,96,5E,3D,ED,61,E6,60,96,5D
10006 DATA 3D,ED,65,E6,60,96,5F,3D,E3,62,ED,62,EC,65,E9,61,89,00,ED,60
10007 DATA EC,63,D3,15,97,16,D7,63,EC,61,D9,14,99,13,DD,14,A6,60,89,00
10008 DATA 97,13,32,67,39

Friday, November 4, 2022

Ahl's Benchmark Revisited

 Ahl's Benchmark is a short BASIC program written by David H. Ahl, and published in Creative Computing.  It was used to compare the speed of different machines back in the 1980s, and results were published for a lot of machines.  The benchmark, and results for many machines can be found in the March 1984 issue.

With the addition of the hardware multiply patch, and 6309 native mode, the CoCo 3 emulator turns on a time of just under 28.6 seconds, and that includes the time to POKE the code into RAM.
 
The IBM PC turned in a time of 24 seconds, and the Amiga 22 (or 14?) seconds.
I timed the 4 MHz Apple IIc Plus at around 31 seconds.
Considering the difference in clock speeds, these results are pretty respectable.




0 TIMER=0:POKE 65497,0

REM GET BASIC TOPRAM POINTER, SUBTRACT SIZE OF USER CODE
1 AD=PEEK(116)*256+PEEK(117)-24

REM RESERVE MEMORY FOR USR CODE
2 CLEAR 100,AD

REM VARIABLES ERASED BY CLEAR, SO REDO AD, POKE USR CODE INTO RAM
3 AD=PEEK(116)*256+PEEK(117):FOR I=0 TO 23:READ B$:A=VAL("&H"+B$):POKE AD+I,A:NEXT

REM DEFINE USR ROUTINES
4 DEFUSR0=AD:DEFUSR1=AD+12

REM ENABLE 6309 NATIVE MODE
5 A=USR0(0)

REM INSTALL HARDWARE MULTIPLY PATCH
6 GOSUB 10000


10 REM Ahl_s simple benchmark
20 FOR N = 1 TO 100: A = N
30 FOR I = 1 TO 10
40 A = SQR(A): R = R + RND(1)
50 NEXT I
60 FOR I = 1 TO 10
70 A = A^2: R = R + RND(1)
80 NEXT I
90 S = S + A: NEXT N
100 PRINT "Accuracy ";ABS (1010-S/5)
110 PRINT "Random ";ABS (1000-R)
120 PRINT "TIMER=";TIMER/60

REM DISABLE 6309 NATIVE MODE
130 A=USR1(0)
140 END


REM USR functions to enable/disable 6309 native mode
9000 DATA CC,FF,FF,10,4F,5D,26,03,11,3D,01,39,CC,FF,FF,10,4F,5D,26,03,11,3D,00,39

REM COCO3 HARDWARE MULTIPLY PATCH.
REM JUST ADD A GOSUB 10000 AT THE TOP OF YOUR CODE TO ADD IT

REM ADDRESS WE ARE STORING THE MULTIPLY PATCH IN RAM
10000 AD=VAL("&HFA0C")

REM POKE THE MULTIPLY PATCH INTO RAM.
10001 FORI=0 TO 64:READ B$:A=VAL("&H"+B$):POKE AD+I,A:NEXT

REM MAKE BASIC JUMP TO OUR MULTIPY INSTEAD OF USING IT'S CODE. $BB00 JMP $FA0C
10002 POKE VAL("&HBB02"),VAL("&H7E"):POKE VAL("&HBB03"),VAL("&HFA"):POKE VAL("&HBB04"),VAL("&H0C")

10003 RETURN

10005 DATA 32,79,E7,60,96,60,3D,ED,63,E6,60,96,5E,3D,ED,61,E6,60,96,5D
10006 DATA 3D,ED,65,E6,60,96,5F,3D,E3,62,ED,62,EC,65,E9,61,89,00,ED,60
10007 DATA EC,63,D3,15,97,16,D7,63,EC,61,D9,14,99,13,DD,14,A6,60,89,00
10008 DATA 97,13,32,67,39

Sunday, October 23, 2022

Make Your Own Maurer Rose Patterns

Maurer Rose patterns based on slightly modified code I posted the other day

This version allows you to input the values for N and D.  Then it displays the results, and waits for a keypress.  Once you hit a key it will return to the text screen and ask for new values.

Here are a couple examples:
 

Values 2,29

 


Values 6,71




0 POKE65497,0:SX=144:SY=56:SZ=64:CX=320:CY=192

5 HSCREEN0:INPUT"ENTER VALUES FOR N,D";N,D

6 IF N=0 OR D=0 THEN 5

REM XO,YO = ORIGIN
10 XO=160:YO=96:PI=22/7:HSCREEN 2


REM DW = DRAW WIDTH
REM T=THETA
20 DW = 1 : HCOLOR 14
30 FOR T = 0 TO 360
40   K = T * D * PI / 180
50   R = 96 * SIN(N * K)
60   X = XO - R * COS(K)
70   Y = YO - R * SIN(K)
80   HLINE-(X, Y),PSET
90 NEXT

100 IF INKEY$="" THEN 100 ELSE 5
 



Saturday, October 22, 2022

Archimedean Spiral

Archimedean Spiral



 0 POKE65497,0:SX=144:SY=56:SZ=64:CX=320:CY=192:HSCREEN 2

10 A=1.5
20 B=1.5
30 PI=3.141592

40 HSET(160,96)

50 FOR T=0 TO 15*PI STEP .1
60  R=A+B*T  
70  HLINE-(160+2*R*SIN(T),96+R*COS(T)),PSET
80 NEXT

100 GOTO 100