O N E   C R A Z Y   M U L T I   T A L E N T Today its Saturday, June 25, 2022 @

Type-in fun (Amiga) - Part #2
in Nostalgia | Thursday, January 18, 2018 | 23:31

3D Star Scroll (a.k.a. Starfield):

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!

3D Starscroll - Machine Code / AmigaBasic code

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

Actually, we don't know it by the name "3D Starscroll", when its actually a sinus centered starfield with shading :-)

It should be noted that in my quick WinUAE test, it seems to work as intended on Amiga Workbench 1.3 with 0.5mb chip, 0mb fast. In addition to OCS and ECS Denise settings. I actually used SEKA V1.5 by KUMA for this one too (reference to my PART #1 in this post-series on my website recently).

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 6-1989 (page 28-29)
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)

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

; ///////////////////
; Title : 3D Starscroll
; By : Kenneth Bernholm
; For : Amiga Interface
; ///////////////////

; From Amiga Interface Magazine Issue 6-1989 (page 28-29)
; Typed/Cleaned up by Stone Oakvalley - 18 January 2018

; NOTE: Works only on Amiga 500 V1.3 with 0.5mb chip, no fast
; and OCS or ECS Denise in my random WinUAE tests.

; To assemble (instructions by Stone Oakvalley):
; Run SEKA V1.5 (Kuma) and set 100 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 stars, mouse button
; to exit works, so does anybody know why it do not 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 shows a nice 3 layered star field!
; 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 ]]]]]

screen1 = $60000
screen2 = screen1+38400
progstart = screen2+38400

; [[[[[ program code ]]]]]

org progstart
load progstart

jsr init_screen ;call : initscreen
jsr init_interrupts ;call : init_interrupts

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

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


;---- clear screens

lea.l screen1,a0 ;a0=adr. of screen1
move.l #19199,d0 ;d0=no. of bytes

clr.l (a0)+ ;clear byte
dbf d0,clear_screens ;loop until d0=0

;---- set bitplane pointers for screen1

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

;---- start my copper_list

move.l 4,a6 ;a6=adr. of exec-library
jsr -132(a6) ;call : forbid
move.l 156(a6),a1 ;al=adr. of gfx-lib.
move.l 38(a1),sys_copper ;store adr. of sys.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
jsr -138(a6) ;call : permit
move.l sys_copper,$dff080 ;start system copper
move.l sys_stack,a7 ;restore system stack
move.w #$8020,$dff096 ;start sprites
rts ;return to main

; ##### 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 intreq
move.w sys_intena,$dff09a ;restore system intena
rts ;return to main

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

movem.l d0-d7/a0-a6,-(a7) ;save registers
move.w $dff01e,d0 ;get intreq
btst #5,d0 ;is it a vb-interrupt
beq.l my_level3_exit ;if not, jump
jsr star_scroll ;call : star_scroll
jsr flip_screen ;call : flip_screen

movem.l (a7)+,d0-d7/a0-a6 ;load registers
move.w #$0020,$dff09c ;kill all vb-requests
move.w #$8020,$dff09a ;enable vb-interrupt
rte ;return

; ##### subprogram : star_scroll #####


;---- delete all stars

lea.l star_area,a0 ;a0=adr. of star_area
move.w #99,d0 ;d0=no. of stars

move.l 12(a0),a2 ;d2=star-adress
move.b #0,(a2) ;clear bitplane 1
move.b #0,12800(a2) ;clear bitplane 2
move.b #0,25600(a2) ;clear bitplane 3
add.l #16,a0 ;move to next star
dbf d0,star_scroll0 ;loop until d0=0

;---- print new stars
lea.l star_area,a0 ;a0=adr. of star_area
move.w #99,d7 ;d7=no. of stars

tst.w (a0) ;star inactive ?
bne.s star_scroll2 ;if not, jump

;---- define new star
moveq #0,d0 ;clear d0
move.w $dff006,d0 ;d0=vposr
move.l d0,d1 ;dl=vposr
lsr.w #8,d1 ;scroll d1 right
eor.b d1,d0 ;d1=rnd-number
and.w #$01ff,d0 ;demask rnd-number
move.w d0,(a0) ;set new star-direction
move.w #0,2(a0) ;set new star-radius
and.w #$0003,d0 ;demask low 3 bits
tst.w d0 ;is d0=0
bne.s xx ;if not, jump
or.w #$0002,d0 ;else set speed2

move.w d0,4(a0) ;c1ear speed and color
move.l screen_adress,8(a0) ;set adr. of screen

;---- move star

move.w 4(a0),d0 ;d0=speed
add.w d0,2(a0) ;add speed to radius
moveq #0,d3 ;d3=0
move.w (a0),d3 ;d3=star-value
lsl.w #1,d3 ;d3=star-value*2
move.l d3,d5 ;d5=d3
lea.l cos_table,a1 ;a1=adr. of cos_table
move.w (a1,d3.w),d3 ;d3=cos(star)
muls 2(a0),d3 ;d3=radius*cos(star)
lsl.l #2,d3 ;d3=d3*4
swap d3 ;swap words in d3
ext.l d3 ;extend result to longword
add.l #184,d3 ;add x-origin to result
lea.l sin_table,a1 ;a1=adr. of sin_table
move.w (a1,d5.w),d5 ;d5=cos(star)
muls 2(a0),d5 ;d5=radius*cos(star)
lsl.l #2,d5 ;d5=d5*4
swap d5 ;swap words in d5
ext.l d5 ;extend result to longword
add.l #100,d5 ;add y-origin to result
cmp.l #0,d3 ;compare x with 0
blt.s star_scroll3 ;if x<0, jump
cmp.l #367,d3 ;compare x with 367
bgt.s star_scroll3 ;if x>367, jump
cmp.l #0,d5 ;compare y with 0
blt.s star_scroll3 ;if y<0, jump
cmp.l #199,d5 ;compare y with 199
bgt.s star_scroll3 ;if y> 199, jump
bra.s star_scroll4 ;jump

move.w #0,(a0) ;stop star
move.l 12(a0),a2 ;get adr. of star
move.b #0,(a2) ;clear bpl1
move.b #0,12800(a2) ;clear bpl2
move.b #0,25600(a2) ;clear bpl3
move.l 8(a0),a2 ;get adr. of other star
move.b #0,(a2) ;clear bpl1
move.b #0,12800(a2) ;clear bpl2
move.b #0,25600(a2) ;clear bpl3
bra.s star_scroll5 ;jump

;---- plot star (d3=x, d5=y)

move.b d3,d4 ;d4=low byte
and.l #$00000007,d4 ;demask scroll-value
lsr.w #3,d3 ;divide d3 with 8
lsl #6,d5 ;d5=d5*64
add.l d5,d3 ;d3=plot-adress
move.l screen_adress,a1 ;a1=screen_adress
add.l d3,a1 ;a1=adr. in screen
move.l 8(a0),12(a0) ;shift screen-adress
move.l a1,8(a0) ;store old adress
move.b #$80,d5 ;d5=star-byte
lsr.b d4,d5 ;scroll star in byte
moveq #0,d0 ;d0=0
move.w 2(a0),d0 ;d0=star-radius
divu #23,d0 ;divide d0 with 23
btst #0,d0 ;speed0 ?
beq.s s1 ;if not, jump
or.b d5,(a1) ;plot star

btst #1,d0 ;speed1 ?
beq.s s2 ;if not, jump
or.b d5,12800(a1) ;plot star

btst #2,d0 ;speed2?
beq.s star_scroll5 ;if not, jump
or.b d5,25600(a1) ;plot star

add.l #16,a0 ;move to next star
dbf d7,star_scroll1 ;loop until d7=0

rts ;return to main

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

cmp.l #screen2,screen_adress ;showing screen1 ?
beq.s flip_screen2 ;if yes, jump

;---- show screen1

lea.l bpl_pointers,a0 ;a0=adr. of bpLpointers
move.l #screen1,d0 ;d0=adr. of screen J
move.w d0,6(a0) ;store low word
swap d0 ;swap words
move.w d0,2(a0) ;store high word
swap d0 ;swap words
add.l #12800,d0 ;move to next bitplane
addq.l #8,a0 ;move to next pointer
move.w d0,6(a0) ;store low word
swap d0 ;swap words
move.w d0,2(a0) ;store high word
swap d0 ;swap words
add.l #12800,d0 ;move to next bitplane
addq.l #8,a0 ;move to next pointer
move.w d0,6(a0) ;store low word
swap d0 ;swap words
move.w d0,2(a0) ;store high word
move.l #screen2,screen_adress ;work on screen2
bra.s flip_screen_exit ;jump

;---- show screen2

lea.l bpl_pointers,a0 ;a0=adr. of bpl_pointers
move.l #screen2,d0 ;d0=adr. of screen2
move.w d0,6(a0) ;store low word
swap d0 ;swap words
move.w d0,2(a0) ;store high word
swap d0 ;swap words
add.l #12800,d0 ;move to next bitplane
addq.l #8,a0 ;move to next pointer
move.w d0,6(a0) ;store low word
swap d0 ;swap words
move.w d0,2(a0) ;store high word
swap d0 ;swap words
add.l #12800,d0 ;move to next bitplane
addq.l #8,a0 ;move to next pointer
move.w d0,6(a0) ;store low word
swap d0 ;swap words
move.w d0,2(a0) ;store high word
move.l #screen1,screen_adress ;work on screen1

rts ;return to main

;---- interrupt reservations ----
dc.w 0 ;systems intreq

dc.w 0 ;systems intena

dc.l 0 ;systems level3 interrupt

;---- system reservations ----
dc.l 0 ;adr. of system copper

dc.l 0 ;adr. of system stack

;---- general reservations ----
dc.l 0 ;adr. of work-screen

;--- starscroll reservations ----

blk.l 200*4,0 ;work-area for starscroll

;---- my copper_list ----

dc.w $0100,$3200 ;bitplane control
dc.w $0104,$0020 ;video priority
dc.w $0102,$0000 ;bitplane scroll-value
dc.w $0108,18 ;bitplane modulo odd
dc.w $010a,18 ;bitplane modulo even
dc.w $008e,$2c81 ;upper-Ieft corner
dc.w $0090,$f4c9 ;bottom-right corner
dc.w $0092,$002a ;bitplane horizontal start
dc.w $0094,$00d4 ;bitplane horizontal stop

dc.w $00e0,$0000 ;bitplane 1 high
dc.w $00e2,$0000 ;bitplane 1 low
dc.w $00e4,$0000 ;bitplane 2 high
dc.w $00e6,$0000 ;bitplane 2 low
dc.w $00e8,$0000 ;bitplane 3 high
dc.w $00ea,$0000 ;bitplane 3 low
dc.w $0180,$0000 ;ink 0
dc.w $0182,$0333 ;ink 1
dc.w $0184,$0555 ;ink 2
dc.w $0186,$0777 ;ink 3
dc.w $0188,$0999 ;ink 4
dc.w $018a,$0bbb ;ink 5
dc.w $018c,$0ddd ;ink 6
dc.w $018e,$0fff ;ink 7
dc.w $2c09,$fffe ;wait for line 2c
dc.w $0180,$0111 ;ink 0
dc.w $f501,$fffe ;wait for line f5
dc.w $0180,$0000 ;ink 0
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 some instructions of what on the disk. Kind of a cover-disk to this story! :-)

SEKA V1.5 by Kuma Computers 1984-1986.

Compiles the .s source fine!

And finally after successfull compiling, a nice centered shaded 3D StarField is shown!

Please review these related article links:
Click to open basSINCON_Generator.bas (AmigaBasic source code)
Click to open s3D_Stars.s (assembly source code)
Click to open adfCover-Disk for this story (Kickstart 1.3) - with SEKA software and files
Click to open urlhttp://www.retro-commodore.eu/amiga-interface/

Posted by: Old-schooler, Stone Oakvalley | Publisher: Website Designer, Stone Oakvalley
Last revised: May 27, 2021 - 10:22 | Page views: 1375

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