O N E   C R A Z Y   M U L T I   T A L E N T Today its Thursday, June 1, 2023 @

Type-in fun (Amiga) - Part #1
in Nostalgia | Sunday, January 14, 2018 | 22:41

Vector Graphics Test:

Back in the days, I always enjoyed reading magazines and almost everytime a piece of code appeared in the magazines for C64 or Amiga, I couldn't resist typing it in and see what happened!

Well, fast forward 30 years later I still can't shake that feeling and urge to do exactly that again. For the past 3months or so I have started reading my huge collection of almost 5000 computer magazines from the early 80's and into the 90's. Starting of A through Z. At this point in time, I'm still at letter A :-)

Anyways, I picked out some of the type-ins that appeared very interresting for me, either based on the fact of stuff I wanted to try back in the days, or actual code snippets that can help me in whatever projects I'm doing on C64 or Amiga these days.

Enjoy a trip into the world of typing matters. Only this time, naturally everything is simply copied as OCR'd text from PDF, double-checked, notes added and code presented below.

I have referenced the issue and page number the original type-in was published in, so if you have the magazine available, read on for more details there!

Vector Graphics - Machine Code / AmigaBasic code

This one was discovered in a Danish magazine called "Amiga Interface" Issue 3-1989 on page 37-38. In fact they had code listings for AmigaBasic and Assembly language in many of their magazines. Download link for magazine at bottom of page.

I am familiar with most languages, but assembly code was never my favourite topic, it was just too darn hard to understand. But still, back in the days I managed to cook together snippets of minimalstic code or just assemble random sources found on various utilities disks and see what happen and kind-of learn something.

30 years later, I decided to give it a go. Only to find my lack of memory regarding what assembler to use, how to use it and understand today how to get it to work. Since I love old-school vector graphics, I spend almost 2 days gathering the following research and successfull results below :-)

I started out thinking I have to rely on the available assembler software used back in 1989. During some research in those Danish magazines, I noticed they used SEKA, and most likely V1.5 by Kuma (not those other MasterSeka hacks, or even SEKA hacks that circulated back then). Further, knowing its 1989, we could assume its was coded (and working) on a plain stock Amiga 500 v1.3 workbench with 0.5m chip and probably 0.5m fast memory.

I loaded up my "AmigaFilesDatabase" in my searcher software (SOTDS) and found a couple of hundred filenames with "seka" in them.

My research showed that there was no difference in compiling the source code in the original SEKA v1.5 by Kuma until the latest version, including MasterSeka v1.80. ASMOne/Devpac/ASMOneTurbo all failed on something.

Oh well, here's a complete gathering of my findings and don't forget to check out the attached links and files at the bottom of this longer post.

First up, the AmigaBasic code which will generate Sin/Cos tables "RAM:TABLES" that where mentioned in the magazine to include inside the assembly source code.

REM From Amiga Interface Magazine Issue 3-1989 (page 37-38)
REM Typed/Cleaned up by Stone Oakvalley January 2018
REM /////////////////////////////////////
PRINT #1,"sin_table:"
FOR a=0 TO 511
PRINT #1,CHR$(9)"dc.w";CHR$(9);INT(b)
PRINT #1,CHR$(13);"cos_table:"
FOR a=0 TO 511
PRINT #1,CHR$(9)"dc.w";CHR$(9);INT(b)

Next, the assembly code to be compiled with SEKA V1.5-V3.2 (excluding v3.0) including MasterSekaV1.80 (at least). For clarity and to remember for myself, I included HOW-TO assemble and save the executable file to disk. It isn't easy when SEKA V1.5 don't have menus or I managed to find any decent user manual, heck, even the original 2 disk-set from Kuma with manual wasn't even found in my gadzillion of files gathered from Internet for the past 10 years either!

It should be noted that the code listed below the sin/cos tables are removed. However, the attached "Realtime_VectorGraphics.s" source file at the bottom is complete with sin/cos tables.

; Title: VGR (Vector Graphics Routines)
; By : Kenneth Bernholm
; For : Amiga Interface

; From Amiga Interface Magazine Issue 3-1989 (page 37-38)
; Typed/Cleaned up by Stone Oakvalley - 14/15 January 2018

; To assemble (instructions by Stone Oakvalley):
; Run SEKA V1.5 (Kuma) and set 300 as memory
; 'r' for loading file from disk (this source)
; 'a' for assemble
; 'OPTIONS>' just leave blank and press return
; 'wo' press return (for writing the executable)
; 'FILENAME>' = enter a filename, example ram:test
; and file is successfully saved as stand-alone executable?!
; The screen will boot up brown, but no spinning vector disk, mouse button
; to exit works, so does anybody know why it don't execute properly?!!

; Or if you want to run it at once directly from SEKA V1.5
; Simple type "a" for assemble, press return to ignore "OPTIONS>"
; and then "jj" (j=jump) and press enter. It will then execute from
; where the "j" label begins and show a nice floppy disk with the
; Amiga checkmark logo rotating in wireframe!
; A good user manual for SEKA (K-SEKA Assembler) found here:
; http://wiki.amigaspirit.hu/index.php/Amiga_Machine_Language_(Chapter_3) and section 3.3

; [[[[[[ memory reservations ]]]]]]

screen0 = $60000
screen1 = screen0+8000
progstart = screen1+8000

org progstart
load progstart

jsr init_interrupts ;call : init _interrupts
jsr init_screen ;call : init_screen

btst #6,$bfe001 ;is left button pressed
bne.s test_left_button ;if yes, jump
jsr restore_screen ;call : restore_screen
jsr restore_interrupts ;call : restore_interrupts
clr.l d0 ;clear exit-vector
rts ;return to dos

; ###### subprogram: init_interrupts #####

move.w $dff01e,sys_intreq ;store system intreq
move.w $dff01c,sys_intena ;store system intena
move.w #$7fff,$dff09c ;kill all requests
move.w #$7fff,$dff09a ;disable all interrupts
move.l $6c,sys_level3 ;store system level3
move.l #my_level3,$6c ;set my level3
move.w #$8020,$dff09a ;enable vb-interrupt
move.w #$c000,$dff09a ;master enable
rts ;return to main

; ###### subprogram: restore_interrupts ######

move.l sys_level3,$6c ;restore system level3
or.w #$8000,sys_intena ;set enable bit
or.w #$8000,sys_intreq ;set enable bit
move.w sys_intreq,$dff09c ;restore system inrreq
move.w sys_intena,$dff09a ;restore system intena
rts ;return to main

; ###### subprogram: init_screen ######

move.l 4,a6 ;a6=adr. of exec-library
move.l 156(a6),a1 ;a1=adr. of gfx-lib.
move.l 38(a1),sys_copper ;store adr. of system copper
move.l a7,sys_stack ;store system stack
move.l #copper_list,$dff080 ;start my copper_list
move.w #$0020,$dff096 ;stop sprites
rts ;return to main

; ##### subprogram: restore_screen ######

move.l 4,a6 ;a6=adr. of exec-library
move.l sys_copper,$dff080 ;start system coppe
move.l sys_stack,a7 ;restore system stack
move.w #$8020,$dff096 ;start sprites
rts ;return to main

; ###### my level3 interrupts ######

btst #5,$dff01f ;is it a vb-interrupt
beq.L my_level3_exit ;if not, jump
jsr draw_figure ;call : draw_figure
move.w #0800,$dff180
jsr flip_screen ;call : flip_screen
move.w #$0020,$dff09c ;kill all vb-requests
rte ;return

; ###### subprogram: flip_screen ######

cmp.l #screen1,screen_adress ;are we showing screen1
beq.s flip_to_screen1 ;if yes, jump

;---- flip to screen()

lea.l bpl_pointers,a0 ;a0=adr. of bpl_pointers
move.l #screen0,d0 ;d0=adr. of screen0
move.w d0,6(a0) ;set low word
swap d0 ;swap high/low words
move.w d0,2(a0) ;set high word
move.l #screen1,screen_adress ;set screen_adress
bra.s flip_screen_exit ;jump

;---- flip to screen1

lea.l bpl_pointers,a0 ;a0=adr. of bpl_pointers
move.l #screen1,d0 ;d0=adr. of screen1
move.w d0,6(a0) ;set low word
swap d0 ;swap high/low words
move.w d0,2(a0) ;set high word
move.l #screen0,screen_adress ;set screen_adress

rts ;return to main

; ##### subprogram : draw_figure #####

btst #14,$dff002 ;is blitter busy
bne.s draw_figure ;if yes, jump
move.l #$01000000,$dff040 ;set control()
move.l screen_adress,$dff054 ;set destination
move.w #0,$dff066 ;set modulo d
move.w #[200*64]+20,$dff058 ;set size (start blitter)
move.l #$00008000,$dff072 ;sel blitter source data
move.l #$ffffffff,$dff044 ;set first mask for a
move.w #40,$dff060 ;modulo c=width

;---- calculate new degrees

move.l xdelta,d0 ;d0=xdelta
add.l d0,xgrad ;set new xgrad
and.l #$000001ff,xgrad ;kill all over 511
move.l ygrad,d6 ;d6=ygrad
add.l ydelta,d6 ;d6=ygrad+ydelta
and.l #$000001ff,d6 ;kill all over 511
move.l d6,ygrad ;store ygrad
lsl.w #1,d6 ;d6=ygrad*4
move.l zgrad,d7 ;d7=zgrad
add.l zdelta,d7 ;d7=zgrad+zdelta
and.l #$000001ff,d7 ;kill all over 511
move.l d7,zgrad ;store zgrad
lsl.w #1,d7 ;d7=zgrad*4

;---- rotate figure

move.l screen_adress,a0 ;a0=adr. of screen
lea.l figure1,a1 ;a1=adr. of figure1
lea.l sin_table,a2 ;a2=adr. of sin_table
lea.l cos_table,a3 ;a3=adr. of cos_lable
lea.l octant_table,a4 ;a4=adr. of octant_table
cmp.w #555,(a1) ;is this the end
beq.L draw_figure_exit ;if yes, jump
move.l xgrad,d5 ;d5=xgrad
lsl.w #1,d5 ;d5=xgrad*4

;---- rotate around x-axis

move.w (a3,d5),d0 ;d0=cos(xgrad)
muls 4(a1),d0 ;d0=y*cos(xgrad)
move.w (a2,d5),d1 ;d1=sin(xgrad)
muls 6(a1),d1 ;d1=z*sin(xgrad)
sub.l d1,d0 ;d0=y*cos(xgrad)-z*sin(xgrad)
lsl.l #2,d0 ;multiply d0 with 4
move.l d0,y1 ;set yl
move.w (a2,d5),d0 ;d0=sin(xgrad)
muls 4(a1),d0 ;d0=y*sin(xgrad)
move.w (a3,d5),d1 ;d1=cos(xgrad)
muls 6(a1),d1 ;d1=z*cos(xgrad)
add.l d1,d0 ;d0=y*sin(xgrad)+z*cos(xgrad)
lsl.l #2,d0 ;multiply d0 with 4
move.l d0,z1 ;set zl

;---- rotate around y-axis

move.w (a3,d6),d0 ;d0=cos(ygrad)
muls 2(a1),d0 ;d0=x*cos(ygrad)
move.w (a2,d6),d1 ;d1=sin(ygrad)
muls z1,d1 ;d1=z*sin(ygrad)
sub.l d1,d0 ;d0=x*cos(ygrad)-z1*sin(ygrad)
lsl.l #2,d0 ;multiply d0 with 4
move.l d0,x2 ;set x2
move.w (a2,d6),d0 ;d0=sin(ygrad)
muls 2(a1),d0 ;d0=x*sin(ygrad)
move.w (a3,d6),d1 ;d1=cos(ygrad)
muls z1,d1 ;d1=z1*cos(ygrad)
add.l d1,d0 ;d0=x*sin(ygrad)+z1*cos(ygrad)
lsl.l #2,d0 ;multiply d0 with 4
swap d0 ;divide d0 with 65535
ext.l d0 ;extend to longword
move.l d0,z2 ;set z2

;---- rotate around z-axis

move.w (a3,d7),d0 ;d0=cos(zgrad)
muls x2,d0 ;d0=x2*cos(zgrad)
move.w (a2,d7),d1 ;d1=sin(zgrad)
muls y1,d1 ;dl=y1*sin(zgrad)
sub.l d1,d0 ;d3=x2*cos(zgrad)-y2*sin(zgrad)
lsl.l #2,d0 ;multiply d0 with 4
swap d0 ;divide d0 with 65535
ext.l d0 ;extend to longword
move.w (a2,d7),d1 ;d1=sin(zgrad)
muls x2,d1 ;d1=x2*sin(zgrad)
move.w (a3,d7),d2 ;d2=cos(zgrad)
muls y1,d2 ;d2=y1*cos(zgrad)
add.l d2,d1 ;d1=x2*sin(zgrad)+y2*cos(zgrad)
lsl.l #2,d1 ;multiply d1 with 4
swap d1 ;divide d1 wilh 65535
ext.l d1 ;extend to longword

;---- translate from 3d to 2d

move.l yviewpoint,d2 ;d2=yviewpoint
muls d0,d2 ;d2=yviewpoint*x3
move.l viewdistance,d4 ;d4=viewdistance
add.l d1,d4 ;d4=viewdistance+y3
divs d4,d2 ;d2=d2/d4
ext.l d2 ;extend to longword
add.l xorigo,d2 ;add xorigo to x-position
move.l last_x_point,d0 ;d0=x1
move.l d2,last_x_point ;store x-position
move.l d1,d3 ;d3=y3
add.l yorigo,d3 ;d3=y3+yorigo
move.l zviewpoint,d4 ;d4=zviewpoint
sub.l z2,d4 ;d4=zviewpoint-z2
muls d3,d4 ;d4=d4*d3
add.l viewdistance,d1 ;d1=viewdistance+y3
divs d1,d4 ;d4=d4/d1
ext.l d4 ;extend to longword
add.l z2,d4 ;add z2 to d4
lsr.l #1,d4 ;d4=y4/2
move.l zorigo,d3 ;d3=zorigo
sub.l d4,d3 ;d3=zorigo-y4/2 = y2
move.l last_y_point,d1 ;d1=yl
move.l d3,last_y_point ;store y-position

;---- draw line

tst.w (a1) ;move?
beq.L draw_figure3 ;if yes, jump
cmp.l d0,d2 ;compare x-coords
bne.l draw1 ;if not equal, jump
cmp.l d1,d3 ;compare y-coords
bne.L draw1 ;if not equal, jump
bra.l draw_figure3 ;jump

;---- d4=start-adress for line

move.l d1,d4 ;d4=yl
move.l d4,d5 ;d5=yl
lsl.w #5,d4 ;d4=yl*32
lsl.w #3,d5 ;d5=yl*8
add.l d5,d4 ;d4=y1*40
move.l d0,d5 ;d5=xl
lsr.w #3,d5 ;d5=xl/8
add.l d5,d4 ;add d5 to d4
add.l a0,d4 ;add bitplane-adress to d4

;---- calculate octant & delta

move.l #0,d5 ;clear d5
sub.w d1,d3 ;d3=deltay (y2-y1)
roxl.b #1,d5 ;scroll neg-sign in deltay
tst.w d3 ;restore n-flag ?
bge.s y2gy1 ;jump if deltay is positive
neg.w d3 ;else invert deltay

y2gy1: sub.w d0,d2 ;d2=deltax (x2-x1)
roxl.b #1,d5 ;scroll neg-sign in deltax
tst.w d2 ;restore n-flag
bge.s x2gx1 ;jump if deltax is positive
neg.w d2 ;else invert deltax

move.w d3,d1 ;d1=deltay
sub.w d2,d1 ;dl=deltay-deltax
bge.s dygdx ;jump if deltay>deltax
exg d2,d3 ;d2=smallest data

dygdx: roxl.b #1,d5 ;d5=number of actual octant
move.b (a4,d5),d5 ;d5=octant-code
lsl.l #1,d2 ;d2=smallest data*2
and.w #$000f,d0 ;first 4 bits of x1
ror.w #4,d0 ;set shift-value
or.w #$0bfa,d0 ;set use/miniterms
move.l d3,d1 ;d1=d3
lsl.w #6,d3 ;d3=length*64
addq.w #2,d3 ;d3=length*64+2

draw99: btst #14,$dff002 ;test blitter-busy bit
bne.s draw99 ;if not set, loop
move.w d2,$dff062 ;set modulo b
sub.w d1,d2 ;d2=d2-greatest data
bge.s signn1 ;jump if 2*kdelta>gdelta
or.b #$40,d5 ;set signed-flag

signn1: move.w d2,$dff052 ;set pointer a (low word)
sub.w d1,d2 ;d2=d2-d3
move.w d2,$dff064 ;set modulo a

;---- initialize other blitter-registers

move.w d0,$dff040 ;set shift and minterms
move.w d5,$dff042 ;set octant no.
move.l d4,$dff048 ;set start-adress af line
move.l d4,$dff054 ;set start-adress of line
move.w #40,$dff066 ;modulo d=width
move.w d3,$dff058 ;start blitter

addq.l #8,a1 ;move to next 3d-data
bra.L draw_figure2 ;jump

rts ;return to main

;---- interrupt reservations ----
sys_intreq: dc.w 0 ;systems intreq
sys_intena: dc.w 0 ;systems intena
sys_level3: dc.l 0 ;systems level3 interrupt

;---- system reservations ----
sys_copper: dc.l 0 ;adr. of system copper
sys_stack: dc.l 0 ;adr.of system stack

;---- screen reservations ----
screen_adress: dc.l screen0

;---- vector reservations -----
dc.b %00000001 ;y1
dc.b %00010001 ;y1dy = octant7

dc.b %00001001 ;y1x2, dx
dc.b %00010101 ;y1x2, dx>dy = octant4

dc.b %00000101 ;y1>y2, x1
dc.b %00011001 ;y1>y2, x1dy = octant0

dc.b %00001101 ;y1>y2, xl>x2, dx
dc.b %00011101 ;y1>y2, x1>x2, dx>dy = octant3

xorigo: dc.l 160
yorigo: dc.l -100
zorigo: dc.l 100
yviewpoint: dc.l 250
zviewpoint: dc.l 0
viewdistance: dc.l 300
xgrad: dc.l 0
ygrad: dc.l 0
zgrad: dc.l 0
xdelta: dc.l 5
ydelta: dc.l 3
zdelta: dc.l 1
y1: dc.l 0
z1: dc.l 0
x2: dc.l 0
z2: dc.l 0
last_x_point: dc.l 0
last_y_point: dc.l 0

; command(0=move,1=draw),x,z,y

dc.w 0,-65,0,65,1,65,0,65,1,65,0,-80,1,-57,0,-80,1,-65,0,-72,1,-65,0,65,0,-53,0,65
dc.w 1,-53,0,-20,1,53,0,-20,1,53,0,65,0,55,0,55,1,61,0,55,1,61,0,49,1,55,0,49
dc.w 1,55,0,55,0,-34,0,-80,1,-34,0,-34,1,53,0,-34,1,53,0,-80,1,32,0,-80,1,32,0,-34
dc.w 0,-24,0,-73,1,-24,0,-37,1,-8,0,-37,1,-8,0,-73,1,-24,0,-73,0,-40,0,30,1,-15,0,0
dc.w 1,25,0,55,0,-30,0,30,1,-5,0,0,1,35,0,55,0,-20,0,30,1,5,0,0,1,45,0,55,0,-65,50,65
dc.w 1,65,50,65,1,65,50,-80,1,-57,50,-80,1,-65,50,-72,1,-65,50,65,0,-53,50,65
dc.w 1,-53,50,-20,1,53,50,-20,1,53,50,65,0,55,50,55,1,61,50,55,1,61,50,49,1,55,50,49
dc.w 1,55,50,55,0,-34,50,-80,1,-34,50,-34,1,53,50,-34,1,53,50,-80,1,32,50,-80
dc.w 1,32,50,-34,555,555,555,555

;---- my copper_list ----
dc.w $0100,$1200 ;bitplane control
dc.w $0104,$0024 ;video priority
dc.w $0102,$0000 ;bitplane scroll-value
dc.w $0108,$0000 ;bitplane modulo odd
dc.w $010a,$0000 ;bilplane modulo even
dc.w $008e,$2c81 ;window upper-left corner
dc.w $0090,$f4c1 ;window bottom-right corner
dc.w $0092,$0038 ;datafeteh start
dc.w $0094,$00d0 ;datafeteh stop

dc.w $00e0,$0007 ;bitplane 1 high
dc.w $00e2,$5000 ;bitplane 1 low

dc.w $0180,$0000 ;ink 0
dc.w $0182,$00f0 ;ink 1

dc.w $ffff,$fffe ;wait for vbi

; ##### table of sinus-values from 0 to 511 ####

; inject the "RAM:TABLES" file created with the AmigaBasic source here

dc.b 'the end',0


Finally, to top it all off, I included every SEKA version I could find, created a bootable V1.3 disk with minor CLI commands for you, both source code listed above and also some instructions of what on the disk. Kind of a cover-disk to this story! :-)

I also included which is probably the only suitable manual for SEKA (K-SEKA) and other assemblers on Amiga "http://wiki.amigaspirit.hu/index.php/Amiga_Machine_Language_(Chapter_3)".

Since I don't trust other sites to be "out there" as long as I have intended, I took the liberty of copy/paste the SEKA section and uploaded that file to my server too!

In fact, I get so frustrated that there isn't any "love" for K-SEKA. Everybody seems to hate it. For this matter, I found a Danish/English Machine Code course that uses K-SEKA as their reference. At least something!

SEKA V1.5 by Kuma Computers 1984-1986.

Compiles the .s source fine!

A most likely hacked or modified version for the better :-)

Tagged: SEKA v1.5 by (MEGAFORCE 1988 - Austria)
With and additional comment "SEKA Version 2.0 Coded by ACE"

Compiles the .s source fine!

Yet another hack/modfied version.

Tagged: "MEGAFORCE 1988 - Austria" and "HARDWARE FAILURE 1989 - SWEDEN".

Still it says V1.5. Well, now we are getting confuzed?!

Compiles the .s source fine!

And bummer. Seems their hacking started to fail.

Tagged: "Kefrens SEKA V3.0 Assembler" with additional comments that it was based on original V1.5, but added all features of V2.1 by Ace of Megaforce".

Only to be destroyed by Kefrens?! What the hell?

As you can see, the .s source didn't compile fine, but spits out some random garble about something.

And yet another hack again. At least this time it says "SEKA v3.0"
but modified "by the KID for sinners 12/11/1988 france, uk"

So... another group making V3.0 while Kefrens messed up V3.0?

The sanity isn't here anymore. Overlapping version numbers and we don't know really what was based on what now again, do we?

I guess its explainable as there was no internet back then, only swapping disks so that kind of "knowing what version something was currently hacked as", wouldn't come as fast as we would wish.

Oh, well, at least the .s source code compiled fine with this version too.

And finally Kefrens comes along and restores their glory.

Tagged "SEKA V3.2 Improved by PROMAX of KEFRENS in 1989".

This one finally compiles the .s source code fine :-)


Since MasterSeka spew out of the original SEKA V1.5 and got tweaked so much they decided to call it "Master of SEKA" probably as it was really much much better.

It included also menus, file-requesters and more. It has earned its own way of life indeed. However, I will not cover the multiple variants of MasterSeka's history in this story. This was all about 1989, original SEKA and a source code from a magazine that wanted to be compiled in 2018 the right way :-)

Here's a note I found:
"MasterSeka V1.0 is based on the Seka V3.0 of Promax/Kefrens, so here first their instructions:

The SEKA V3.0 is based on the SEKA V1.5 not the SEKA V2.1 by MFC. Anyhow this version supports all SEKA V2.1 commands. The upgrade programming was done by Promax of Kefrens"

To be honest and possibly for historic reasons, I would like to know why KUMA stopped at SEKA V1.5 and never continued to develop it. Was there even a SEKA version lower than 1.5?

In fact I haven't seen any stories or any files I came across to indicate nothing else than V1.5 exists, but who knows, maybe you (visitor) know the story of that :-)

And my self-built "Cover Disk" for this story. Basically it sums up everything already written, but nice to have everything all piled up into one ADF disk image for further/future studies by myself or somebody else for that matter.

Download link at bottom of this page.

And finally after such a long post and hard research, the fruits of the compiled code is shown:

A nice double layered Amiga Floppy Disk with the Amiga Checkmark logo rotating in Vector Graphics. Phew.

Please review these related article links:
Click to open basSINCON_Generator.bas (AmigaBasic source code)
Click to open sRealtime_VectorGraphics.s (assembly source code)
Click to open adfCover-Disk for this story (Kickstart 1.3) - with SEKA software and files
Click to open urlhttp://wiki.amigaspirit.hu/index.php/Amiga_Machine_Language_(Chapter_3)
Click to open txtseka_(k-seka)_manual.txt
Click to open urlDataskolens brevkursus (Danish/English) - for K-SEKA!
Click to open urlhttp://www.retro-commodore.eu/amiga-interface/

Posted by: Old-schooler, Stone Oakvalley | Publisher: Website Designer, Stone Oakvalley
Last revised: December 07, 2022 - 17:31 | Page views: 3097

Website Design by post@stone-oakvalley-studios.com - Copyright © 2023 www.stone-oakvalley-studios.com