Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@hollance
Created November 23, 2016 19:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save hollance/974ecc6cf7fe9d91a3033b075ca6f0b1 to your computer and use it in GitHub Desktop.
Save hollance/974ecc6cf7fe9d91a3033b075ca6f0b1 to your computer and use it in GitHub Desktop.
Zero Gravity source code (Amiga 1200)
; *****************************************************************************
;
; $VER: ZeroGravity Source 1.0 (C) 1997 Matthijs Hollemans
;
; *****************************************************************************
;
; This is the full source code to Zero Gravity. I used the very cool ASM-One
; V1.29 assembler from T.F.A. but that doesn't matter anyway because you won't
; be able to reassemble this without the required binary includes...
;
; *****************************************************************************
SHOW equ 0 ; 1 = Show rastertiming, 0 = Don't
DEBUG equ 1 ; 1 = Debug-mode on, 0 = Normal
ASMOne equ 1 ; 1 = Assemble for ASMOne, 0 = Make executable
run IFNE ASMOne ;
jsr Init ;
illegal ;
ELSE ;
jsr WBInit ;
jsr Init ;
jsr WBDone ;
rts ;
ENDC ;
; =============================================================================
;
; S Y S T E M S T A R T U P / E X I T R O U T I N E S
;
; =============================================================================
; *****************************************************************************
; Macros
; *****************************************************************************
CLRMEM MACRO ; Clear memory pool size
memptr set 0 ;
ENDM ;
ADDMEM MACRO ; Request memory
\1 set memptr ; \1 = Offset in memory pool
memptr set memptr+\2 ; \2 = Size of required memory
ENDM ;
ALIGNLONG MACRO ; Align to longword
CNOP 0,4 ;
ENDM ;
ALIGNQUAD MACRO ; Align to quadword
CNOP 0,8 ;
ENDM ;
; *****************************************************************************
; WBInit
; *****************************************************************************
WBInit clr.l ReturnMsg ;
move.l $4.w,a6 ;
sub.l a1,a1 ;
jsr -294(a6) ; FindTask(NULL)
move.l d0,a4 ;
tst.l $ac(a4) ; Called from CLI?
bne.b .Done ;
move.l $4.w,a6 ;
lea $5c(a4),a0 ; pr_MsgPort
jsr -384(a6) ; WaitPort()
lea $5c(a4),a0 ; pr_MsgPort
jsr -372(a6) ; GetMsg()
move.l d0,ReturnMsg ; Save message for later reply
.Done
rts
; *****************************************************************************
; WBDone
; *****************************************************************************
WBDone tst.l ReturnMsg ; Called from CLI ?
beq.b .Done ; Then skip next bit
move.l $4.w,a6 ;
jsr -132(a6) ; Forbid()
move.l ReturnMsg,a1 ; Send message back
jsr -378(a6) ; ReplyMsg()
.Done
move.l ReturnCode,d0 ; Returncode
rts
; *****************************************************************************
; Init
; *****************************************************************************
Init ; Open libraries ------------------------------------------------------
move.l $4.w,a6 ;
lea intname,a1 ;
moveq #0,d0 ;
jsr -552(a6) ; OpenLibrary()
move.l d0,intuibase ;
beq.w nointui ;
lea grafname,a1 ;
moveq #0,d0 ;
jsr -552(a6) ; OpenLibrary()
move.l d0,gfxbase ;
beq.w nogfx ;
lea dosname,a1 ;
moveq #0,d0 ;
jsr -552(a6) ; OpenLibrary()
move.l d0,dosbase ;
beq.w nodos ;
; Check for AGA -------------------------------------------------------
move.l gfxbase,a6 ;
btst.b #2,$ec(a6) ; gb_ChipRevBits0
beq.w noaga ;
; Allocate chip memory ------------------------------------------------
move.l $4.w,a6 ;
move.l #chip+65536,d0 ; (64k border because of slow copper)
move.l #$2,d1 ; MEMF_CHIP
jsr -198(a6) ; AllocMem()
move.l d0,chipmem ;
beq.w nochip ;
; Allocate other memory -----------------------------------------------
move.l #fast+8192,d0 ; (8k border for 040 caches)
move.l #$10000,d1 ; MEMF_CLEAR
jsr -198(a6) ; AllocMem()
move.l d0,fastmem ;
beq.w nofast ;
; Close Workbench -----------------------------------------------------
IFEQ ASMOne ;
move.l intuibase,a6 ;
jsr -78(a6) ; CloseWorkBench()
move.l d0,wbclosed ; Store result
ENDC ;
; Reset screen hardware -----------------------------------------------
move.l gfxbase,a6 ;
move.l $22(a6),oldview ; gb_ActiView
sub.l a1,a1 ;
jsr -222(a6) ; LoadView(NULL)
jsr -270(a6) ; WaitTOF()
jsr -270(a6) ; WaitTOF()
jsr -228(a6) ; WaitBlit()
jsr -456(a6) ; OwnBlitter()
move.w #0,$dff01fc ; Reset AGA sprites
move.w #0,$dff0106 ;
; Kill multitasking ---------------------------------------------------
move.l $4.w,a6 ;
jsr -132(a6) ; Forbid()
; Get VBR -------------------------------------------------------------
move.l $4.w,a6 ; Switch to supervisor mode, because
lea .get(pc),a5 ; movec is a privileged instruction.
jsr -$1e(a6) ; Supervisor()
bra.b .store ;
.get movec vbr,d0 ; (dc.l $4e7a0801)
rte ;
.store move.l d0,_vbr ; Store VBR
; Int3 Vector ---------------------------------------------------------
move.w $dff002,d0 ; Save DMACON
ori.w #$8000,d0 ;
move.w d0,olddmacon ;
move.w $dff01c,d0 ; Save INTENA
ori.w #$c000,d0 ;
move.w d0,oldintena ;
move.w #$7fff,$dff09a ; Kill interrupts
move.w #$7fff,$dff09c ;
move.w #$7fff,$dff096 ; Kill DMA
move.l _vbr,a0 ;
move.l $6c(a0),oldint3 ; Store old Int3 vector
; *****************************************************************************
; Main
; *****************************************************************************
jsr Main
; *****************************************************************************
; Done
; *****************************************************************************
Done ; Restore interrupt vectors -------------------------------------------
move.w #$7fff,$dff09a ; Kill interrupts
move.w #$7fff,$dff09c ;
move.w #$7fff,$dff096 ; Kill DMA
move.l _vbr,a0 ;
move.l oldint3,$6c(a0) ;
move.w olddmacon,$dff096 ; Restore DMACON
move.w oldintena,$dff09a ; Restore INTENA
; Enable multitasking -------------------------------------------------
move.l $4.w,a6 ;
jsr -138(a6) ; Permit()
; Restore screen ------------------------------------------------------
move.l gfxbase,a6 ;
move.l oldview,a1 ;
jsr -222(a6) ; LoadView(oldview)
jsr -462(a6) ; DisownBlitter()
move.l $26(a6),$dff080 ; gb_copinit
move.l #0,$dff088 ;
; Open Workbench ------------------------------------------------------
IFEQ ASMOne ;
tst.l wbclosed ; IF Workbench was closed
beq.b .wbopen ;
move.l intuibase,a6 ;
jsr -210(a6) ; OpenWorkBench()
.wbopen ; ENDIF
ENDC ;
; Free memory and close libraries -------------------------------------
move.l $4.w,a6 ;
move.l fastmem,a1 ;
move.l #fast+8192,d0 ;
jsr -210(a6) ; FreeMem()
nofast
move.l $4.w,a6 ;
move.l chipmem,a1 ;
move.l #chip+65536,d0 ;
jsr -210(a6) ; FreeMem()
nochip
noaga
move.l 4,a6 ;
move.l dosbase,a1 ;
jsr -414(a6) ; CloseLibrary()
nodos
move.l 4,a6 ;
move.l gfxbase,a1 ;
jsr -414(a6) ; CloseLibrary()
nogfx
move.l 4,a6 ;
move.l intuibase,a1 ;
jsr -414(a6) ; CloseLibrary()
nointui
move.l ReturnCode,d0 ;
rts
; *****************************************************************************
; Data
; *****************************************************************************
ALIGNLONG
ReturnMsg dc.l 0 ; Workbench message
ReturnCode dc.l 0 ; CLI return code
_vbr dc.l 0 ; VBR address
oldint3 dc.l 0 ; Old Int3 vector
oldview dc.l 0 ; Old view
olddmacon dc.w 0 ; Old DMACON
oldintena dc.w 0 ; Old INTENA
chipmem dc.l 0 ; Amount of required chipmem
fastmem dc.l 0 ; Amount of required fastmem
dosbase dc.l 0 ; DOSBase
gfxbase dc.l 0 ; GFXBase
intuibase dc.l 0 ; IntuiBase
wbclosed dc.l 0 ; 0 = Unable to close Workbench
dosname dc.b "dos.library",0
grafname dc.b "graphics.library",0
intname dc.b "intuition.library",0
; =============================================================================
;
; M A I N P R O G R A M
;
; =============================================================================
; *****************************************************************************
; Macros
; *****************************************************************************
PPUTSTR MACRO ; PPUTSTR StringPtr,PlanarBufferOffset
movem.l d0-d7/a0-a6,-(sp) ;
move.l \1,a0 ;
move.l chipmem,a1 ;
add.l #scr0,a1 ;
add.l \2,a1 ;
bsr PPutStr ;
movem.l (sp)+,d0-d7/a0-a6 ;
ENDM ;
PPUTCHR MACRO ; PPUTCHR Character,PlanarBufferOffset
movem.l d0-d7/a0-a6,-(sp) ;
moveq #0,d0 ;
move.l \1,d0 ;
move.l chipmem,a1 ;
add.l #scr0,a1 ;
add.l \2,a1 ;
bsr PPutChr ;
movem.l (sp)+,d0-d7/a0-a6 ;
ENDM ;
PPUTNUM MACRO ; PPUTNUM Number,PlanarBufferOffset
movem.l d0-d7/a0-a6,-(sp) ;
move.l \1,d0 ;
add.l #48,d0 ;
move.l chipmem,a1 ;
add.l #scr0,a1 ;
add.l \2,a1 ;
bsr PPutChr ;
movem.l (sp)+,d0-d7/a0-a6 ;
ENDM
CPUTSTR MACRO ; CPUTSTR StringPtr,ChunkyBufferOffset
movem.l d0-d7/a0-a6,-(sp) ;
lea \1,a0 ;
move.l RendCh,a1 ;
add.l \2,a1 ;
bsr CPutStr ;
movem.l (sp)+,d0-d7/a0-a6 ;
ENDM ;
CPUTCHR MACRO ; CPUTCHR Character,ChunkyBufferOffset
movem.l d0-d7/a0-a6,-(sp) ;
moveq #0,d0 ;
move.l \1,d0 ;
move.l RendCh,a1 ;
add.l \2,a1 ;
bsr CPutChr ;
movem.l (sp)+,d0-d7/a0-a6 ;
ENDM ;
CPUTNUM MACRO ; CPUTNUM Number,ChunkyBufferOffset
movem.l d0-d7/a0-a6,-(sp) ;
moveq #0,d0 ;
move.l \1,d0 ;
add.l #48,d0 ; Convert Number to ASCII
move.l RendCh,a1 ;
add.l \2,a1 ;
bsr CPutChr ;
movem.l (sp)+,d0-d7/a0-a6 ;
ENDM ;
; *****************************************************************************
; Memory
; *****************************************************************************
CLRMEM ;
ADDMEM shit,8 ; If I leave this bit out, then the
; cop0 copperlist gets totally fucked
; up. This is related to mt_init. Why ?
ADDMEM cop0,8192 ; Copperlists
ADDMEM cop1,8192 ;
ADDMEM ch0,160*128 ; Chunky buffers
ADDMEM ch1,160*128 ;
ADDMEM scr0,320*128 ; Screens
ADDMEM scr1,320*128 ;
ADDMEM buf2,160*128*2 ; Pass-buffer (160*128/2 ???)
ADDMEM sblbuf,160*128 ; Scramble-buffer
ADDMEM sprbuf,(312*8*2)*8 ; Sprite buffer
ADDMEM chipend,1 ;
chip equ chipend ; Amount of required chipmem
CLRMEM ;
ADDMEM blist0,40*1024 ; Blitlist buffers
ADDMEM blist1,40*1024 ;
ADDMEM fastend,1 ;
fast equ fastend ; Amount of required fastmem
; *****************************************************************************
; Raw key codes
; *****************************************************************************
KEY_NONE = $00 ; No key pressed
KEY_NEW = $01 ; New key pressed
KEY_REPEAT = $02 ; Key repeated
KEY_F1 = $50
KEY_F2 = $51
KEY_F3 = $52
KEY_F4 = $53
KEY_F5 = $54
KEY_F6 = $55
KEY_F7 = $56
KEY_F8 = $57
KEY_F9 = $58
KEY_F10 = $59
KEY_Q = $10
KEY_W = $11
KEY_E = $12
KEY_R = $13
KEY_T = $14
KEY_Y = $15
KEY_U = $16
KEY_I = $17
KEY_O = $18
KEY_P = $19
KEY_A = $20
KEY_S = $21
KEY_D = $22
KEY_F = $23
KEY_G = $24
KEY_H = $25
KEY_J = $26
KEY_K = $27
KEY_L = $28
KEY_Z = $31
KEY_X = $32
KEY_C = $33
KEY_V = $34
KEY_B = $35
KEY_N = $36
KEY_M = $37
KEY_ESC = $45
KEY_ENTER = $44
KEY_SPACE = $40
KEY_BACKSPACE = $41
; *****************************************************************************
; Types
; *****************************************************************************
Type_HoleX1 equ 0 ; }_ TopLeft-coordinates of hole
Type_HoleY1 equ 2 ; }
Type_HoleX2 equ 4 ; }_ BottomRight-coordinates of hole
Type_HoleY2 equ 6 ; }
Level_sizeof equ 8 ;
Level_NumWall equ 0 ; Total number of walls
Level_Ships equ 2 ; Number of ships
Level_Time equ 4 ; Time (in ticks)
Coll_BoundsX1 equ 0 ; }_ TopLeft-coordinates of
Coll_BoundsY1 equ 2 ; } collision boundary
Coll_BoundsX2 equ 4 ; }_ BottomRight-coordinates of
Coll_BoundsY2 equ 6 ; } collision boundary
; *****************************************************************************
; Constants
; *****************************************************************************
TRUE = 1 ; }_ Boolean values
FALSE = 0 ; }
BufferW = 160 ; }_ Chunky buffer dimensions
BufferH = 128 ; }
ClipL = 0 ; }
ClipR = BufferW-1 ; }_ Clipping borders
ClipT = 0 ; }
ClipB = BufferH-1 ; }
CenterX = BufferW/2 ; }_ Center of chunky buffer
CenterY = BufferH/2 ; }
ViewD = 256*32*2/8 ; Maximum visible depth
RealZ = 200 ; Adjust player Z-coordinate
MinSpd = 0 ; Minimum speed
MaxSpd = 25600 ; Maximum speed
Plyr_XInit = 80 ; }_ Initial player coordinates
Plyr_YInit = 75 ; }
Plyr_XMin = 32 ; }
Plyr_XMax = BufferW-32 ; }_ Min/Max. player coordinates
Plyr_YMin = 32 ; }
Plyr_YMax = BufferH-32 ; }
XAccel = 1 ; }
YAccel = 1 ; }- Acceleration
ZAccel = 256 ; }
NumLevel = 5 ; Number of levels
MaxWall = 128 ; Max. number of walls per level
Flg_Normal = 0 ; Game-loop status flags
Flg_Collision = 1 ; Hit a wall
Flg_LevelDone = 2 ; Flying away from level
Flg_LevelInit = 3 ; Flying to new level
Flg_GetReady = 4 ; Ready to start new level
Flg_NewShip = 5 ; Ready to start new life
Flg_OutOfTime = 6 ; No time left
Flg_RaceOver = 7 ; Crashed too many times
Flg_Pause = 8 ; Pause mode
Flg_Quit = 99 ; Leaving game-loop
WT_Start = 0 ; Wall types
WT_Finish = 1 ;
WT_Left = 2 ;
WT_Right = 3 ;
WT_Up = 4 ;
WT_Down = 5 ;
IFlg_Text = 0 ; Show intro-text
IFlg_AskName = 1 ; User enters name
IFlg_TrackSel = 2 ; Track select
IFlg_Quit = 99 ; Leaving intro-loop
IFlg_QuitToWB = 100 ; Leaving intro-loop and exit to WB
MaxStrLen = 11 ; Max. length of input string
; *****************************************************************************
; Code
; *****************************************************************************
ALIGNLONG
Main bsr.b InitMain ; Initialisation
.Intro bsr.w Intro ; Do intro
cmp.l #IFlg_QuitToWB,Intro_Flags ; IF player pressed ESC ?
beq.b .Done ; THEN exit
bsr.w InitLevel ;
bsr.w GameLoop ;
bra.b .Intro ;
.Done
bsr.w DoneMain ; Clean up
rts ;
; =============================================================================
;
; G A M E R O U T I N E S
;
; =============================================================================
; *****************************************************************************
; InitMain
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: First initialisation.
; Notes : -
; Scratch : -
; Author : -
; History : -
; *****************************************************************************
InitMain
; Copy bitplane pointers to intro copperlist --------------------------
lea IntroCopBpl,a2 ; a2=Position in copperlist header
move.l #IntroPic,d0 ; d0=Screen address
move.w #6-1,d7 ; Write 6 bitplanes
.mkbpl swap d0 ;
move.w d0,2(a2) ; Write MSW
swap d0 ;
move.w d0,6(a2) ; Write LSW
addq.l #8,a2 ; Next position in copperlist
add.l #320*256/8,d0 ; Next bitplane
dbf d7,.mkbpl ;
; Copy sprite pointers to intro copperlist ----------------------------
lea IntroCopSpr,a2 ; a2=Position in copperlist header
move.l #SpriteData,d0 ; d0=Address of sprite data
move.w #8-1,d7 ; Write 8 sprites
.mkspr swap d0 ;
move.w d0,2(a2) ; Write MSW
swap d0 ;
move.w d0,6(a2) ; Write LSW
addq.l #8,a2 ; Next position in copperlist
dbf d7,.mkspr ;
; Make BlitterScreen copperlists --------------------------------------
move.l chipmem,a0 ;
add.l #cop0,a0 ; a0=Copperlist 0
move.l chipmem,a1 ;
add.l #scr0,a1 ; a1=Screen 0
bsr.w mkbltscr ; Create copperlist
move.l chipmem,a0 ;
add.l #cop1,a0 ; a0=Copperlist 1
move.l chipmem,a1 ;
add.l #scr1,a1 ; a1=Screen 1
bsr.w mkbltscr ; Create copperlist
; Init double buffering pointers --------------------------------------
move.l fastmem,RendBL ;
add.l #blist0,RendBL ;
move.l fastmem,DispBL ;
add.l #blist1,DispBL ;
move.l chipmem,RendCh ;
add.l #ch0,RendCh ;
move.l chipmem,DispCh ;
add.l #ch1,DispCh ;
move.l chipmem,RendCop ;
add.l #cop0,RendCop ;
move.l chipmem,DispCop ;
add.l #cop1,DispCop ;
; Other stuff ---------------------------------------------------------
bsr.w LoadScores ; Init Hall of Fame
bsr.w SetCIAInt ; Set music player interrupt
move.l #IFlg_Text,Intro_Flags ; Start intro at part I
; Finished ------------------------------------------------------------
rts
; *****************************************************************************
; DoneMain
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Cleans up the mess.
; Notes : -
; Scratch : -
; Author : -
; History : -
; *****************************************************************************
DoneMain
bsr.w ResetCIAInt ; Remove music player interrupt
rts
; *****************************************************************************
; Intro
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: -
; Notes : -
; Scratch : All
; Author : -
; History : -
; *****************************************************************************
ALIGNLONG
Intro
; Everything off ------------------------------------------------------
move.w #$7fff,$dff09a ; Kill interrupts
move.w #$7fff,$dff09c ;
move.w #$7fff,$dff096 ; Kill DMA
; Set palette ---------------------------------------------------------
move.l #IntroCopCol,a0 ; Set palette
move.l #IntroPal,a1 ;
bsr.w SetPal24 ;
move.l #IntroCop,$dff080 ; Display copperlist
; Init planes 7 and 8 -------------------------------------------------
lea IntroCopBpl,a2 ; a2=Position in copperlist
add.l #8*6,a2 ;
move.l chipmem,d0 ; Write last two bitplanes
add.l #scr0,d0 ; Plane 7
swap d0 ;
move.w d0,2(a2) ;
swap d0 ;
move.w d0,6(a2) ;
addq.l #8,a2 ;
add.l #20480,d0 ; Plane 8
swap d0 ;
move.w d0,2(a2) ;
swap d0 ;
move.w d0,6(a2) ;
bsr.w ClearPlanes ; Clear planes 7 and 8
; Init stuff ----------------------------------------------------------
move.b #FALSE,Intro_WarpIn ;
move.b #FALSE,Intro_WarpOut ;
move.w #0,Intro_WarpCount ; Reset warp-counter
move.l #-1,Intro_Timer ; Reset timer
move.w Plyr_Level,Intro_Level ; Intro_Level = Plyr_Level
move.w #$e000,$dff09a ; Enable CIA interrupts
move.w #$83af,$dff096 ; Enable BPL+COP+AUDx DMA
; Start music ---------------------------------------------------------
move.l #IntroMusic,mt_data ;
bsr.w mt_init ;
st mt_Enable ;
IntroLoop
; Sync display --------------------------------------------------------
bsr.w WaitVBL ; Wait for vertical blank
add.l #1,Intro_Timer ; Update timer
; WarpIn --------------------------------------------------------------
.WrpIn cmp.b #TRUE,Intro_WarpIn ; WarpIn two last bitplanes
bne.b .WrpOut ;
add.w #1,Intro_WarpCount ; Intro_WarpCount += 1
bsr.w Warp ; Do warp effect
cmp.w #31,Intro_WarpCount ; IF Intro_WarpCount >= 31
blt.b IntroText ; Intro_WarpIn=FALSE
move.b #FALSE,Intro_WarpIn ; ENDIF
; WarpOut -------------------------------------------------------------
.WrpOut cmp.b #TRUE,Intro_WarpOut ; WarpOut two last bitplanes
bne.b IntroText ;
sub.w #1,Intro_WarpCount ; Intro_WarpCount -= 1
bsr.w Warp ; Do warp effect
cmp.w #0,Intro_WarpCount ; IF Intro_WarpCount <= 0
bgt.b IntroText ; Intro_WarpOut=FALSE
move.b #FALSE,Intro_WarpOut ; ENDIF
; Part I: Write text ==================================================
IntroText
cmp.l #IFlg_Text,Intro_Flags ;
bne.w IntroAskName ;
cmp.l #0,Intro_Timer ; CREDITS
bne.w .1 ;
bsr.w ClearPlanes ;
move.b #TRUE,Intro_WarpIn ;
PPUTSTR #itxt_1,#40*280+20 ;
PPUTSTR #itxt_0,#40*296+20 ;
PPUTSTR #itxt_1,#40*312+20 ;
PPUTSTR #itxt_2,#40*360+20 ;
PPUTSTR #itxt_3,#40*376+20 ;
PPUTSTR #itxt_4,#40*392+20 ;
PPUTSTR #itxt_5,#40*424+20 ;
PPUTSTR #itxt_6,#40*440+20 ;
PPUTSTR #itxt_7,#40*456+20 ;
PPUTSTR #itxt_8,#40*472+20 ;
.1 cmp.l #150,Intro_Timer ;
bne.b .2 ;
move.b #TRUE,Intro_WarpOut ;
.2 cmp.l #200,Intro_Timer ; MORE CREDITS
bne.w .3 ;
bsr.w ClearPlanes ;
move.b #TRUE,Intro_WarpIn ;
PPUTSTR #itxt_19,#40*296+20 ;
PPUTSTR #itxt_10,#40*288+20 ;
PPUTSTR #itxt_11,#40*312+20 ;
PPUTSTR #itxt_19,#40*368+20 ;
PPUTSTR #itxt_12,#40*360+20 ;
PPUTSTR #itxt_13,#40*384+20 ;
PPUTSTR #itxt_19,#40*440+20 ;
PPUTSTR #itxt_14,#40*432+20 ;
PPUTSTR #itxt_15,#40*456+20 ;
.3 cmp.l #350,Intro_Timer ;
bne.b .4 ;
move.b #TRUE,Intro_WarpOut ;
.4 cmp.l #400,Intro_Timer ; HALL OF FAME
bne.w .5 ;
bsr.w ClearPlanes ;
move.b #TRUE,Intro_WarpIn ;
PPUTSTR #itxt_20,#40*272+20 ; }
PPUTSTR #itxt_21,#40*288+20 ; }- Write Hall of Fame header
PPUTSTR #itxt_22,#40*304+20 ; }
lea BestTimes,a0 ; a0 = Pointer to BestTimes
lea BestNames,a1 ; a1 = Pointer to BestNames
move.w #NumLevel-1,d7 ; d7 = Loop counter
move.l #0,d1 ; d1 = Level counter
move.l #40*336+21,d2 ; d2 = Screen position
.4loop move.l d1,d0 ; d0 = levelnr
addq.l #1,d0 ; Adjust levelnr
PPUTNUM d0,d2 ; Write track number
move.l d1,d0 ; d0 = levelnr
mulu.w #12,d0 ;
move.l a1,a2 ; a2 = Pointer to BestNames
add.l d0,a2 ; a2 += levelnr*12
move.l d2,a4 ;
add.l #2,a4 ;
PPUTSTR a2,a4 ; Write BestName
move.l d1,d0 ; d0 = levelnr
move.l (a0,d0.w*4),d5 ; d5 = Time
move.l d2,a4 ;
add.l #14,a4 ;
bsr.w PWriteTime ; Write BestTime
addq.l #1,d1 ; Increase level counter
add.l #40*16,d2 ; Increase screen position
dbf d7,.4loop ;
.5 cmp.l #550,Intro_Timer ;
bne.b .0 ;
move.b #TRUE,Intro_WarpOut ;
.0 cmp.l #600,Intro_Timer ;
bne.b .input ;
move.l #-1,Intro_Timer ; Reset intro timer
; Get input -----------------------------------------------------------
.input
bsr.w GetJoy1 ; IF Joy1Fire
tst.b Joy1Fire ;
beq.b .keys ;
move.l #IFlg_AskName,Intro_Flags ; Intro_Flags=IFlg_AskName
move.b #FALSE,Intro_WarpIn ; Stop warp-in
move.b #TRUE,Intro_WarpOut ; Start warp-out
move.l #-1,Intro_Timer ; Reset timer
bra.w IntroQuit ; ENDIF
.keys
bsr.w GetKey ; IF ESC-key pressed
cmp.b #KEY_NEW,KeyState ;
bne.w IntroQuit ;
cmp.b #KEY_ESC,KeyRaw ;
bne.w IntroQuit ;
move.l #IFlg_QuitToWB,Intro_Flags ; Intro_Flags=IFlg_QuitToWB
bra.w IntroQuit ; ENDIF
; Part II: Ask user name ==============================================
IntroAskName
cmp.l #IFlg_AskName,Intro_Flags ;
bne.w IntroTrackSel ;
cmp.l #40,Intro_Timer ; Wait for warp-out finished
blt.w IntroQuit ;
cmp.l #40,Intro_Timer ;
bne.w .0 ;
bsr.w ClearPlanes ; Erase planes 7 & 8
PPUTSTR #ian_0,#40*356+20 ;
PPUTSTR #ian_1,#40*372+20 ;
PPUTSTR #ian_2,#40*388+20 ;
PPUTSTR #ian_3,#40*404+20 ;
move.b #TRUE,Intro_WarpIn ; Start warp-in
.0 cmp.l #80,Intro_Timer ; Wait for warp-in finished
blt.w IntroQuit ;
bsr.w GetStr ; Read player name
move.l #IFlg_TrackSel,Intro_Flags ; Go to part III
move.b #FALSE,Intro_WarpIn ; Stop warp-in
move.b #TRUE,Intro_WarpOut ; Start warp-out
move.l #-1,Intro_Timer ; Reset timer
bra.w IntroQuit ;
; Part III : Track Select =============================================
IntroTrackSel
cmp.l #IFlg_TrackSel,Intro_Flags ;
bne.w IntroQuit ;
cmp.l #40,Intro_Timer ; Wait for warp-out finished
blt.w IntroQuit ;
cmp.l #40,Intro_Timer ; WRITE TRACK INFO
bne.w .input ;
move.b #TRUE,Intro_WarpIn ; Start warp-in
bsr.w ClearPlanes ; Erase planes 7 & 8
PPUTSTR #its_0,#40*264+20 ; }
PPUTSTR #its_1,#40*280+20 ; }- Header
PPUTSTR #its_2,#40*296+20 ; }
PPUTSTR #its_3,#40*320+20 ; TRACK
PPUTSTR #its_4,#40*336+20 ; TIME
PPUTSTR #its_5,#40*352+20 ; SHIPS
PPUTSTR #its_6,#40*384+20 ; BEST
PPUTSTR #its_7,#40*424+20 ; }
PPUTSTR #its_8,#40*440+20 ; }
PPUTSTR #its_9,#40*456+20 ; }- Joystick info
PPUTSTR #its_10,#40*472+20 ; }
PPUTSTR #its_11,#40*488+20 ; }
moveq #0,d0 ;
move.w Intro_Level,d0 ; d0 = Current selected levelnr
move.l d0,d2 ;
move.l d0,d1 ;
addq.w #1,d1 ; Adjust levelnr
PPUTNUM d1,#40*320+34 ; Write Intro_Level
mulu.w #Level_sizeof,d0 ;
lea Level,a0 ;
move.w Level_Ships(a0,d0.w),d1 ;
PPUTNUM d1,#40*352+34 ; Write Level_Ships
move.l Level_Time(a0,d0.w),d5 ;
move.l #40*336+31,a4 ;
bsr.w PWriteTime ; Write Level_Time
lea BestTimes,a0 ;
move.l (a0,d2.w*4),d5 ;
move.l #40*400+34,a4 ;
bsr.w PWriteTime ; Write BestTime
lea BestNames,a1 ;
mulu.w #12,d2 ;
add.l d2,a1 ;
PPUTSTR a1,#40*400+22 ; Write BestName
; Get input -----------------------------------------------------------
.input
cmp.b #FALSE,Intro_WarpOut ; IF Warping-in
bne.w .keys ; THEN skip joystick part
cmp.b #FALSE,Intro_WarpIn ; IF Warping-out
bne.w .keys ; THEN skip joystick part
bsr.w GetJoy1 ; IF Joy1Fire
tst.b Joy1Fire ;
beq.b .nofire ;
move.l #IFlg_Quit,Intro_Flags ; Play selected level !
bra.w IntroQuit ; ENDIF
.nofire tst.b Joy1Left ; IF Joy1Left
beq.b .noleft ;
move.l #-1,Intro_Timer ; Warp
move.b #TRUE,Intro_WarpOut ;
sub.w #1,Intro_Level ; Intro_Level -= 1
bpl.w IntroQuit ; IF Intro_Level < 0
move.w #0,Intro_Level ; THEN Intro_Level = 0
move.l #$7fff,Intro_Timer ;
move.b #FALSE,Intro_WarpOut ; Don't warp
bra.w IntroQuit ; ENDIF
.noleft tst.b Joy1Right ; IF Joy1Right
beq.b .keys ;
move.l #-1,Intro_Timer ; Warp
move.b #TRUE,Intro_WarpOut ;
add.w #1,Intro_Level ; Intro_Level += 1
cmp.w #NumLevel,Intro_Level ; IF Intro_Level = NumLevel
blt.b IntroQuit ; THEN Intro_Level=NumLevel-1
sub.w #1,Intro_Level ;
move.l #$7fff,Intro_Timer ; Don't warp
move.b #FALSE,Intro_WarpOut ;
bra.b IntroQuit ; ENDIF
.keys
bsr.w GetKey ; IF ESC-key pressed
cmp.b #KEY_NEW,KeyState ;
bne.b IntroQuit ;
cmp.b #KEY_ESC,KeyRaw ;
bne.b IntroQuit ;
move.l #IFlg_Text,Intro_Flags ; Back to part I
move.b #FALSE,Intro_WarpIn ; Stop warp-in
move.b #TRUE,Intro_WarpOut ; Start warp-out
move.l #550,Intro_Timer ; Reset timer
bra.w IntroQuit ; ENDIF
; Quit ? ==============================================================
IntroQuit
IFNE DEBUG ;
btst #2,$dff016 ; Check right mousebutton
bne.b .z ;
move.l #IFlg_QuitToWB,Intro_Flags ;
.z ENDC ;
cmp.l #IFlg_Quit,Intro_Flags ; Quit intro-loop ?
blt.w IntroLoop ;
; Finished ------------------------------------------------------------
move.w Intro_Level,Plyr_Level ; Play this level
bsr.w mt_end ; Stop music
move.w #$7fff,$dff09a ; Kill interrupts
move.w #$7fff,$dff09c ;
move.w #$7fff,$dff096 ; Kill DMA
rts
; *****************************************************************************
; ClearPlanes
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Erase intro screen plane 7 and 8.
; Notes : -
; Scratch : -
; Author : -
; History : -
; *****************************************************************************
ClearPlanes ;
move.l chipmem,a0 ; Use scr0 buffer for last two
add.l #scr0,a0 ; bitplanes.
move.w #320*128/4-1,d7 ;
moveq #0,d0 ;
.clr1 move.l d0,(a0)+ ;
dbf d7,.clr1 ;
rts
; *****************************************************************************
; Warp
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Do intro warp effect.
; Notes : -
; Scratch : All
; Author : -
; History : -
; *****************************************************************************
Warp
move.w Intro_WarpCount,d1 ; d1 = Index in IntroWarp table
lea IntroWarp,a0 ; a0 = Pointer to IntroWarp table
lea IntroCopBpl+6*8,a2 ; a2 = Position in copperlist header
move.l chipmem,d0 ;
add.l #scr0,d0 ; Plane 7
add.l (a0,d1.w*4),d0 ; Add warp offset
swap d0 ;
move.w d0,2(a2) ;
swap d0 ;
move.w d0,6(a2) ;
addq.l #8,a2 ;
add.l #20480,d0 ; Plane 8
swap d0 ;
move.w d0,2(a2) ;
swap d0 ;
move.w d0,6(a2) ;
rts
; *****************************************************************************
; InitLevel
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: -
; Notes : -
; Scratch : -
; Author : -
; History : -
; *****************************************************************************
InitLevel
; Clear chunky buffers and screens ------------------------------------
move.l chipmem,a0 ; Note: chunky buffers must be
add.l #ch0,a0 ; allocated after each other
move.w #2*160*128/4-1,d7 ; in memory.
.clr0 move.l #0,(a0)+ ;
dbf d7,.clr0 ;
move.l chipmem,a0 ; Note: screen buffers must be
add.l #scr0,a0 ; allocated after each other
move.w #2*320*128/4-1,d7 ; in memory.
.clr1 move.l #0,(a0)+ ;
dbf d7,.clr1 ;
; Set palette ---------------------------------------------------------
move.l RendCop,a0 ; Set colours to black
add.l #CopCol-Cop,a0 ;
move.l #GamePal,a1 ;
bsr.w SetPal24 ;
move.l DispCop,a0 ;
add.l #CopCol-Cop,a0 ;
move.l #GamePal,a1 ;
bsr.w SetPal24 ;
; DMA & Interrupts ----------------------------------------------------
move.w #$7fff,$dff09a ; Kill interrupts
move.w #$7fff,$dff09c ;
move.w #$7fff,$dff096 ; Kill DMA
move.l _vbr,a0 ;
move.l #int3,$6c(a0) ; INT3 vector
move.l DispCop,$dff080 ; Display copperlist
move.w #$e060,$dff09a ; Enable BLIT+VERTB+CIA ints
move.w #$83cf,$dff096 ; Enable BPL+COP+BLT+AUD DMA
; Make BlitterScreen --------------------------------------------------
move.l chipmem,a0 ;
add.l #ch0,a0 ; Chunky buffer
move.l chipmem,a1 ;
add.l #scr0,a1 ; Planar screen
move.l chipmem,a2 ;
add.l #buf2,a2 ; Pass buffer
move.l chipmem,a3 ;
add.l #sblbuf,a3 ; Scramble buffer
move.l fastmem,a6 ;
add.l #blist0,a6 ; Blitterlist buffer
move.l #160*128,d0 ; Number of chunky pixels
move.l #320*128/8,d1 ; Bytes between the bitplanes
movem.l d0-d7/a0-a6,-(sp) ;
jsr c2bs ; Make blitterlist 0
movem.l (sp)+,d0-d7/a0-a6 ;
move.l chipmem,a0 ;
add.l #ch1,a0 ; Chunky buffer
move.l chipmem,a1 ;
add.l #scr1,a1 ; Planar screen
move.l chipmem,a2 ;
add.l #buf2,a2 ; Pass buffer
move.l chipmem,a3 ;
add.l #sblbuf,a3 ; Scramble buffer
move.l fastmem,a6 ;
add.l #blist1,a6 ; Blitterlist buffer
move.l #160*128,d0 ; Number of chunky pixels
move.l #320*128/8,d1 ; Bytes between the bitplanes
movem.l d0-d7/a0-a6,-(sp) ;
jsr c2bs ; Make blitterlist 1
movem.l (sp)+,d0-d7/a0-a6 ;
; Start the music -----------------------------------------------------
move.l #GameMusic,mt_data ;
bsr.w mt_init ;
st mt_Enable ;
; Init variables ------------------------------------------------------
move.w Plyr_Level,d1 ; d1 = Plyr_Level
move.l #Level,a0 ; Calculate Game_LevelPtr
move.w d1,d0 ;
mulu #Level_sizeof,d0 ;
add.l d0,a0 ;
move.l a0,Game_LevelPtr ;
move.l #Wall_Z,a0 ; Calculate Game_WallZ
move.w d1,d0 ;
mulu #MaxWall*4,d0 ;
add.l d0,a0 ;
move.l a0,Game_WallZ ;
move.l #Wall_Type,a0 ; Calculate Game_WallType
move.w d1,d0 ;
mulu #MaxWall*2,d0 ;
add.l d0,a0 ;
move.l a0,Game_WallType ;
move.w #Plyr_XInit,Plyr_X ; Init player position
move.w #Plyr_YInit,Plyr_Y ;
move.w #0,Plyr_XSpd ; Init player speed
move.w #0,Plyr_YSpd ;
move.w #0,Plyr_Scroll ;
move.l #0,Plyr_Z ;
move.w #28*256,Plyr_ZSpd ;
move.w #0,Plyr_Frame ; Current frame number
move.w #7,Plyr_EngineCnt ; Current engine colour
move.w #TRUE,Plyr_EngineOn ; Engine is on...
move.l #Flg_LevelInit,Game_Flags ; Init flags
move.w #0,Game_FirstWall ; Init walls
move.w #0,Game_LastWall ;
lea Plyr_Name,a0 ; IF Plyr_Name="MOTHERGOOSE"
move.l (a0)+,d0 ;
cmp.l #"MOTH",d0 ;
bne.b .nocht ;
move.l (a0)+,d0 ;
cmp.l #"ERGO",d0 ;
bne.b .nocht ;
move.l (a0)+,d0 ;
cmp.l #$4f534500,d0 ;
bne.b .nocht ;
move.w #9,Plyr_Ships ; Plyr_Ships=9
move.l #29950,Plyr_Time ; Plyr_Time=9:59
move.b #TRUE,Plyr_Cheat ; Plyr_Cheat=TRUE
bra.b .Done ; ELSE
.nocht move.l Game_LevelPtr,a0 ;
move.w Level_Ships(a0),Plyr_Ships ; Plyr_Ships=Level_Ships
move.l Level_Time(a0),Plyr_Time ; Plyr_Time=Level_Time
move.b #FALSE,Plyr_Cheat ; Plyr_Cheat=FALSE
; Finished ------------------------------------------------------------
.Done
rts
; *****************************************************************************
; GameLoop
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: -
; Notes : -
; Scratch : -
; Author : -
; History : -
; *****************************************************************************
ALIGNLONG
GameLoop
; Sync display --------------------------------------------------------
.busy tst.w bltbsy ; Wait for C2P finished
bne.b .busy ; (bltbsy=0)
bsr.w WaitVBL ; Wait for vertical blank
move.l RealTimeCnt,RealTime ; Store realtime counter
move.l #0,RealTimeCnt ; Reset realtime counter
move.l DispCop,$dff080 ; Display copperlist
move.l RendBL,d0 ; Do double buffering
move.l DispBL,RendBL ;
move.l d0,DispBL ;
move.l RendCh,d1 ;
move.l DispCh,RendCh ;
move.l d1,DispCh ;
move.l RendCop,d2 ;
move.l DispCop,RendCop ;
move.l d2,DispCop ;
; Start C2P -----------------------------------------------------------
move.l DispBL,bltpc ; Blitterlist
move.w #1,bltbsy ; Important!
move.w #$8040,$dff09c ; Request blitter interrupt
; Render stuff --------------------------------------------------------
bsr.w DrawTunnel ;
bsr.w DoWalls ;
bsr.w DoPlayer ;
bsr.b DoStatus ;
IFNE SHOW ;
move.w #$f00,$dff182 ; Show rastertiming
ENDC ;
; Quit ? --------------------------------------------------------------
cmp.l #Flg_Quit,Game_Flags ; Quit gameloop ?
bne.w GameLoop ;
.c2pend tst.w bltbsy ; Make sure C2P is finished
bne.b .c2pend ; before we continue
; Finished ------------------------------------------------------------
.Done
bsr.w mt_end ; Stop music
move.l #IFlg_TrackSel,Intro_Flags ; Restart intro at Track Select
rts
; *****************************************************************************
; DoStatus
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Draws status stuff in chunky buffer.
; Notes : -
; Scratch : -
; Author : -
; History : -
; *****************************************************************************
DoStatus
cmp.l #Flg_LevelInit,Game_Flags ; IF Game_Flags=Flg_LevelInit
beq.b .Done ; THEN don't draw status
cmp.l #Flg_GetReady,Game_Flags ; IF Game_Flags=Flg_GetReady
beq.b .Done ; THEN don't draw status
cmp.l #Flg_LevelDone,Game_Flags ; IF Game_Flags=Flg_LevelDone
beq.b .Done ; THEN don't draw status
; Number of ships -----------------------------------------------------
move.w Plyr_Ships,d1 ;
CPUTNUM d1,#160+160-10 ;
; Time left -----------------------------------------------------------
move.l #160,a4 ;
move.l Plyr_Time,d5 ;
bsr.w CWriteTime ;
; Finished ------------------------------------------------------------
.Done
rts
; *****************************************************************************
; DoPlayer
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Does player things.
; Notes : -
; Scratch : None
; Author : -
; History : -
; *****************************************************************************
ALIGNLONG
DoPlayer
movem.l d0-d7/a0-a6,-(sp) ; Save regs
; Normal mode ---------------------------------------------------------
cmp.l #Flg_Normal,Game_Flags ; Normal mode ?
beq.w .Player ;
; LevelInit -----------------------------------------------------------
cmp.l #Flg_LevelInit,Game_Flags ; Level starts
bne.b .getrdy ;
sub.w #ZAccel,Plyr_ZSpd ; Plyr_ZSpd -= ZAccel
cmp.w #0,Plyr_ZSpd ; IF Plyr_ZSpd < 0
bge.w .Keys ;
move.w #0,Plyr_ZSpd ; Plyr_ZSpd = 0
move.l #Flg_GetReady,Game_Flags ; Game_Flags=Flg_GetReady
move.w #FALSE,Plyr_EngineOn ; Stop Engine
bra.w .Keys ; ENDIF
; GetReady ------------------------------------------------------------
.getrdy cmp.l #Flg_GetReady,Game_Flags ; Waiting until player ready
bne.w .nwship ;
.0 CPUTSTR txt_track,#40+38*160 ; Write "TRACK"
move.w Plyr_Level,d1 ;
add.w #1,d1 ; +1 !!!
CPUTNUM d1,#112+38*160 ; Write Plyr_Level
CPUTSTR txt_time,#40+48*160 ; Write "TIME"
move.l #88+48*160,a4 ;
move.l Plyr_Time,d5 ;
bsr.w CWriteTime ;
CPUTSTR txt_ships,#40+58*160 ; Write "SHIPS"
move.w Plyr_Ships,d1 ;
CPUTNUM d1,#112+58*160 ; Write Plyr_Ships
tst.l Toggle ; IF Toggle-bit set
beq.b .gtrdy2 ;
CPUTSTR txt_press,#40+84*160 ; THEN Write "PRESS"
CPUTSTR txt_fire,#88+84*160 ; Write "FIRE"
.gtrdy2 bsr.w GetJoy1 ;
tst.b Joy1Fire ; IF Fire-button
beq.w .Keys ;
move.l #Flg_Normal,Game_Flags ; Game_Flags=Flg_Normal
bra.w .Keys ; ENDIF
; NewShip -------------------------------------------------------------
.nwship cmp.l #Flg_NewShip,Game_Flags ; Player has been resurrected
bne.b .ldone ;
tst.l Toggle ; IF Toggle-bit set
beq.b .nwshp2 ;
CPUTSTR txt_press,#40+84*160 ; THEN Write "PRESS"
CPUTSTR txt_fire,#88+84*160 ; Write "FIRE"
.nwshp2 bsr.w GetJoy1 ;
tst.b Joy1Fire ; IF Fire-button
beq.w .Keys ;
move.l #Flg_Normal,Game_Flags ; Game_Flags=Flg_Normal
bra.w .Keys ; ENDIF
; LevelDone -----------------------------------------------------------
.ldone cmp.l #Flg_LevelDone,Game_Flags ; Level is completed
bne.w .coll ;
move.w #0,Plyr_XSpd ; No X/Y Speed
move.w #0,Plyr_YSpd ;
move.w #TRUE,Plyr_EngineOn ; Activate engine
cmp.w #28*256,Plyr_ZSpd ; IF Plyr_ZSpd > xxxx
blt.b .lt ;
sub.w #ZAccel,Plyr_ZSpd ; THEN Plyr_ZSpd -= ZAccel
bra.b .ldone1 ;
.lt add.w #ZAccel,Plyr_ZSpd ; ELSE Plyr_ZSpd += ZAccel
.ldone1 tst.l Toggle ; IF Toggle-bit set
beq.w .ldone3 ;
CPUTSTR txt_track,#24+60*160 ; THEN Write "TRACK"
CPUTSTR txt_complete,#72+60*160 ; Write "COMPLETE"
.ldone2 move.l Game_LevelPtr,a1 ; a1 = Pointer to Level array
cmp.b #TRUE,Plyr_Cheat ;
bne.w .ld0 ; IF Plyr_Cheat=TRUE
move.l #29950,d1 ; THEN d1 = 9:59
bra.b .ld1 ;
.ld0 move.l Level_Time(a1),d1 ; ELSE d1 = Level_Time
.ld1 sub.l Plyr_Time,d1 ; d1 = Level_Time - Plyr_Time
lea BestTimes,a2 ; a2 = Pointer to BestTimes
move.w Plyr_Level,d2 ; d2 = Plyr_Level
move.l (a2,d2.w*4),d3 ; d3 = BestTime for Plyr_Level
cmp.l d3,d1 ; IF d1 <= d3
bgt.b .ldone3 ;
CPUTSTR txt_best,#20+40*160 ; THEN Write "BEST"
CPUTSTR txt_track,#56+40*160 ; Write "TRACK"
CPUTSTR txt_time,#108+40*160 ; Write "TIME"
move.l d1,(a2,d2.w*4) ; Write time in BestTimes
lea BestNames,a2 ; a2 = Pointer to BestNames
mulu.w #12,d2 ; d2 = Offset in BestNames
move.w #12-1,d7 ;
lea Plyr_Name,a3 ; a3 = Pointer to player name
.lcopy move.b (a3)+,(a2,d2.w) ; Copy character
addq.w #1,d2 ; Update dest. pointer
dbf d7,.lcopy ;
.ldone3 cmp.l #250,FlgTimer ; IF FlgTimer = 5 secs
ble.w .Keys ;
move.l #Flg_Quit,Game_Flags ; Game_Flags=Flg_Quit
bra.w .Keys ; ENDIF
; Collision -----------------------------------------------------------
.coll cmp.l #Flg_Collision,Game_Flags ; Collision with wall
bne.w .outtim ;
move.w #Plyr_XInit,Plyr_X ; Restore player stuff
move.w #Plyr_YInit,Plyr_Y ;
move.w #0,Plyr_XSpd ;
move.w #0,Plyr_YSpd ;
move.w #0,Plyr_ZSpd ;
move.w #0,Plyr_EngineCnt ;
move.w #FALSE,Plyr_EngineOn ;
cmp.l #50,FlgTimer ; IF 0 <= FlgTimer < 50
bge.b .coll1 ; Explosion handled by VBLint
bra.w .Keys ; ENDIF
.coll1 tst.w Plyr_Ships ; IF Plyr_Ships = 0
bne.b .coll2 ;
move.l #Flg_RaceOver,Game_Flags ; Game_Flags=Flg_RaceOver
bra.w .Keys ; ENDIF
.coll2 cmp.l #100,FlgTimer ; IF 50 <= FlgTimer < 100
bge.b .coll3 ;
move.l RealTime,d0 ;
mulu.w #10,d0 ;
add.l d0,Plyr_Z ; Move forward through tunnel
move.l RealTime,d0 ;
mulu.w #2560,d0 ;
add.w d0,Plyr_Scroll ; until wall has disappeared
bra.w .Keys ; ENDIF
.coll3 move.l #Flg_NewShip,Game_Flags ; IF FlgTimer = 100
bra.w .Keys ; THEN Game_Flags=Flg_NewShip
; OutOfTime -----------------------------------------------------------
.outtim cmp.l #Flg_OutOfTime,Game_Flags ; No time left
bne.w .racovr ;
sub.w #ZAccel,Plyr_ZSpd ; Plyr_ZSpd -= ZAccel
cmp.w #0,Plyr_ZSpd ; IF Plyr_ZSpd < 0
bge.b .outt0 ; Plyr_ZSpd = 0
move.w #0,Plyr_ZSpd ; ENDIF
move.w #0,Plyr_XSpd ;
move.w #0,Plyr_YSpd ;
move.w #FALSE,Plyr_EngineOn ; Stop engine
.outt0 tst.l Toggle ; IF Toggle-bit set
beq.b .outt1 ;
CPUTSTR txt_out,#36+60*160 ; THEN Write "OUT"
CPUTSTR txt_of,#68+60*160 ; Write "OF"
CPUTSTR txt_time,#92+60*160 ; Write "TIME"
.outt1 cmp.l #250,FlgTimer ; IF FlgTimer > 5 secs
ble.w .Keys ;
move.l #Flg_Quit,Game_Flags ; Game_Flags=Flg_Quit
bra.w .Keys ; ENDIF
; RaceOver ------------------------------------------------------------
.racovr cmp.l #Flg_RaceOver,Game_Flags ; Race Over
bne.b .pause ;
tst.l Toggle ; IF Toggle-bit set
beq.b .racov1 ;
CPUTSTR txt_race,#44+60*160 ; THEN Write "RACE"
CPUTSTR txt_over,#84+60*160 ; Write "OVER"
.racov1 cmp.l #250,FlgTimer ; IF FlgTimer > 5 secs
ble.w .Keys ;
move.l #Flg_Quit,Game_Flags ; Game_Flags=Flg_Quit
bra.w .Keys ; ENDIF
; Pause ---------------------------------------------------------------
.pause cmp.l #Flg_Pause,Game_Flags ; Game paused
bne.b .EndFlg ;
tst.l Toggle ; IF Toggle-bit set
beq.b .pause1 ;
CPUTSTR txt_pause,#60+60*160 ; THEN Write "PAUSE"
.pause1 bsr.w GetKey ; Read keyboard
cmp.b #KEY_NEW,KeyState ; IF previous key repeated
bne.w .Done ; THEN skip everything
cmp.b #KEY_P,KeyRaw ;
bne.w .Done ; IF P was pressed
move.l #Flg_Normal,Game_Flags ; Resume game
bra.w .Done ; ENDIF
.EndFlg bra.w .Keys ; Unknown flag. Never get here!
; Handle joystick input -----------------------------------------------
.Player bsr.w GetJoy1 ; Read joystick
move.l RealTime,d0 ;
move.l #ZAccel,d1 ; ZAccel = RealTime * ZAccel
mulu.w d0,d1 ;
move.l #XAccel,d2 ; XAccel = RealTime * XAccel
mulu.w d0,d2 ;
move.l #YAccel,d3 ; YAccel = RealTime * YAccel
mulu.w d0,d3 ;
tst.b Joy1Fire ; Fire ?
beq.b .nofire ;
move.w #TRUE,Plyr_EngineOn ; Activate engine
add.w d1,Plyr_ZSpd ; Plyr_ZSpd += ZAccel
cmp.w #MaxSpd,Plyr_ZSpd ; IF Plyr_ZSpd > MaxSpd
ble.b .tstup ;
move.w #MaxSpd,Plyr_ZSpd ; Plyr_ZSpd = MaxSpd
bra.b .tstup ; ENDIF
.nofire
move.w #FALSE,Plyr_EngineOn ; Stop engine
sub.w d1,Plyr_ZSpd ; Plyr_ZSpd -= ZAccel
cmp.w #MinSpd,Plyr_ZSpd ; IF Plyr_ZSpd < MinSpd
bge.b .tstup ; Plyr_ZSpd = MinSpd
move.w #MinSpd,Plyr_ZSpd ; ENDIF
.tstup ;
tst.b Joy1Up ; Up ?
beq.b .noup ;
sub.w d3,Plyr_YSpd ; Plyr_YSpd -= YAccel
bra.b .tstdn ;
.noup tst.w Plyr_YSpd ; IF Plyr_YSpd < 0
bpl.b .tstdn ;
add.w d3,Plyr_YSpd ; Plyr_YSpd += YAccel
bmi.b .tstdn ; IF Plyr_YSpd > 0 THEN Plyr_YSpd=0
move.w #0,Plyr_YSpd ; ENDIF
.tstdn ;
tst.b Joy1Down ; Down ?
beq.b .nodn ;
add.w d3,Plyr_YSpd ; Plyr_YSpd += YAccel
bra.b .tstlt ;
.nodn tst.w Plyr_YSpd ; IF Plyr_YSpd > 0
bmi.b .tstlt ;
sub.w d3,Plyr_YSpd ; Plyr_YSpd -= YAccel
bpl.b .tstlt ; IF Plyr_YSpd < 0 THEN Plyr_YSpd=0
move.w #0,Plyr_YSpd ; ENDIF
.tstlt ;
tst.b Joy1Left ; Left ?
beq.b .nolt ;
sub.w d2,Plyr_XSpd ; Plyr_XSpd -= XAccel
bra.b .tstrt ;
.nolt tst.w Plyr_XSpd ; IF Plyr_XSpd < 0
bpl.b .tstrt ;
add.w d2,Plyr_XSpd ; Plyr_XSpd += XAccel
bmi.b .tstrt ; IF Plyr_XSpd > 0 THEN Plyr_XSpd=0
move.w #0,Plyr_XSpd ; ENDIF
.tstrt ;
tst.b Joy1Right ; Right ?
beq.b .nort ;
add.w d2,Plyr_XSpd ; Plyr_XSpd += XAccel
bra.b .Keys ;
.nort tst.w Plyr_XSpd ; IF Plyr_XSpd > 0
bmi.b .Keys ;
sub.w d2,Plyr_XSpd ; Plyr_XSpd -= XAccel
bpl.b .Keys ; IF Plyr_XSpd < 0 THEN Plyr_XSpd=0
move.w #0,Plyr_XSpd ; ENDIF
; Handle keyboard input -----------------------------------------------
.Keys bsr.w GetKey ; Read keyboard input
cmp.b #KEY_NEW,KeyState ; IF previous key repeated
bne.b .move ; THEN skip this part
move.b KeyRaw,d0 ;
cmp.b #KEY_ESC,d0 ; IF ESC pressed ?
bne.b .P ;
move.l #Flg_Quit,Game_Flags ; Game_Flags=Flg_Quit
bra.w .Done ; ENDIF
.P cmp.b #KEY_P,d0 ; IF P pressed ?
bne.b .move ;
cmp.l #Flg_Normal,Game_Flags ; IF Game_Flags=Flg_Normal
bne.b .move ;
move.l #Flg_Pause,Game_Flags ; THEN Game_Flags=Flg_Pause
bra.w .Done ; ENDIF
; Move player ---------------------------------------------------------
.move moveq #0,d0 ;
move.w Plyr_ZSpd,d0 ; Plyr_Scroll += Plyr_ZSpd
add.w d0,Plyr_Scroll ;
lsr.w #8,d0 ; Plyr_Z += (Plyr_ZSpd/256)
add.l d0,Plyr_Z ;
move.w Plyr_XSpd,d0 ; Plyr_X += Plyr_XSpd
add.w d0,Plyr_X ;
move.w Plyr_YSpd,d0 ; Plyr_Y += Plyr_YSpd
add.w d0,Plyr_Y ;
; Check for boundaries ------------------------------------------------
move.w Plyr_X,d0 ;
cmp.w #Plyr_XMin,d0 ; IF Plyr_X < Plyr_XMin
bge.b .chkrt ;
move.w #Plyr_XMin,Plyr_X ; Plyr_X = Plyr_XMin
move.w #0,Plyr_XSpd ; Plyr_XSpd = 0
bra.b .chkup ;
.chkrt cmp.w #Plyr_XMax,d0 ; ELSEIF Plyr_X > Plyr_XMax
ble.b .chkup ; Plyr_X = Plyr_XMax
move.w #Plyr_XMax,Plyr_X ; Plyr_XSpd = 0
move.w #0,Plyr_XSpd ; ENDIF
.chkup move.w Plyr_Y,d0 ;
cmp.w #Plyr_YMin,d0 ; IF Plyr_Y < Plyr_YMin
bge.b .chkdn ;
move.w #Plyr_YMin,Plyr_Y ; Plyr_Y = Plyr_YMin
move.w #0,Plyr_YSpd ; Plyr_YSpd = 0
bra.b .Time ;
.chkdn cmp.w #Plyr_YMax,d0 ; ELSEIF Plyr_Y > Plyr_YMax
ble.b .Time ; Plyr_Y = Plyr_YMax
move.w #Plyr_YMax,Plyr_Y ; Plyr_YSpd = 0
move.w #0,Plyr_YSpd ; ENDIF
; Check Time ----------------------------------------------------------
.Time cmp.l #Flg_Normal,Game_Flags ; IF Flg_Normal not set
bne.b .Done ; THEN skip this part
cmp.l #0,Plyr_Time ;
bgt.b .Done ; IF Plyr_Time <= 0
move.l #0,Plyr_Time ; THEN Plyr_Time=0
move.l #Flg_OutOfTime,Game_Flags ; Game_Flags=Flg_OutOfTime
; Finished ------------------------------------------------------------
.Done
IFNE DEBUG ;
btst #2,$dff016 ; Check right mousebutton
bne.b .z ;
move.l #Flg_Quit,Game_Flags ;
.z ENDC ;
movem.l (sp)+,d0-d7/a0-a6 ; Restore regs
rts
; *****************************************************************************
; DrawPlayer
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Draws player. Draws shadow. Changes engine colour.
; Notes : -
; Scratch : All
; Author : -
; History : -
; *****************************************************************************
ALIGNLONG
DrawPlayer
cmp.l #Flg_Collision,Game_Flags ; IF Flg_Collision
beq.w .Done ; THEN don't draw player
cmp.l #Flg_RaceOver,Game_Flags ; IF Flg_RaceOver
beq.w .Done ; THEN don't draw player
; Calculate destination pointers --------------------------------------
movem.l d0-d7/a0-a6,-(sp) ;
move.l RendCh,a1 ; a1 = Pointer for ship
moveq #0,d0 ;
moveq #0,d1 ;
move.w Plyr_Y,d0 ;
sub.w #12,d0 ; Adjust Y-position
move.w d0,d1 ; }
lsl.w #7,d0 ; }_ Y * 160
lsl.w #5,d1 ; }
add.w d1,d0 ; }
add.l d0,a1 ;
move.w Plyr_X,d1 ;
sub.w #21,d1 ; Adjust X-position
add.l d1,a1 ;
move.l RendCh,a3 ; a3 = Pointer for shadow
add.l d1,a3 ;
add.l #100*160,a3 ; Y-position
; In what column is player ? ------------------------------------------
moveq #0,d1 ;
move.w Plyr_X,d1 ;
sub.w #32-12,d1 ; Adjust X-postion
divu.w #24,d1 ; Col.nr = X-position / Column_width
move.w d1,d0 ;
move.w d1,d4 ; ShadowFrame.nr = Col.nr
lsl.w #2,d0 ; Frame.nr = Col.nr * 5
add.w d1,d0 ;
; In what row is player ? ---------------------------------------------
moveq #0,d2 ;
move.w Plyr_Y,d2 ;
sub.w #32-8,d2 ; Adjust Y-position
lsr.w #4,d2 ; Row.nr = Y-postion / Row_height
add.w d2,d0 ; Frame.nr += Row.nr
move.w d0,Plyr_Frame ; Store frame number (for coll. checks)
; Draw shadow ---------------------------------------------------------
lea Shadow_Anim,a2 ;
move.l (a2,d4.w*4),a0 ; Get source pointer
move.l #25-1,d6 ; Height = 25 lines
.sloop1 move.w #48-1,d7 ; Width = 48 columns (actually 42!)
.sloop2 move.b (a0)+,d1 ; Read byte
beq.b .sskip ; IF transparent THEN skip write
move.b d1,(a3) ; Write byte
.sskip addq.l #1,a3 ; Go to next pixel
dbf d7,.sloop2 ;
add.l #160-48,a3 ; Go to next row
dbf d6,.sloop1 ;
; Draw ship -----------------------------------------------------------
lea Ship_Anim,a2 ;
move.l (a2,d0.w*4),a0 ; Get source pointer
move.l #25-1,d6 ; Height = 25 lines
.loop1 move.w #48-1,d7 ; Width = 48 columns (actually 42!)
.loop2 move.b (a0)+,d0 ; Read byte
beq.b .skip ; IF transparent THEN skip write
move.b d0,(a1) ; Write byte
.skip addq.l #1,a1 ; Go to next pixel
dbf d7,.loop2 ;
add.l #160-48,a1 ; Go to next row
dbf d6,.loop1 ;
; Change engine colour in copperlist ----------------------------------
move.w Plyr_EngineCnt,d0 ; d0 = Offset in colour table
cmp.w #TRUE,Plyr_EngineOn ; IF Plyr_EngineOn = TRUE
bne.b .false ;
addq.w #1,d0 ; Plyr_EngineCnt += 1
cmp.w #7,d0 ; IF Plyr_EngineCnt > 7
ble.b .store ; THEN Plyr_EngineCnt = 7
moveq #7,d0 ;
bra.b .store ; ELSE
.false subq.w #1,d0 ; Plyr_EngineCnt -= 1
bpl.b .store ; IF Plyr_EngineCnt < 0
moveq #0,d0 ; THEN Plyr_EngineCnt = 0
.store move.w d0,Plyr_EngineCnt ; ENDIF
lea EnginePal,a1 ; a1 = Pointer to colour table
move.l (a1,d0.w*4),d1 ; d1 = Colour (24-Bit HLi)
move.l RendCop,a0 ; a0 = Pointer to copperlist
add.l #CopCol-Cop+394,a0 ;
move.w d1,132(a0) ; Write low 12 bits
swap d1 ;
move.w d1,(a0) ; Write high 12 bits
movem.l (sp)+,d0-d7/a0-a6 ;
; Finished ------------------------------------------------------------
.Done
rts
; *****************************************************************************
; DoWalls
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Draws all visible walls and player.
; Notes : -
; Scratch : All
; History : -
; *****************************************************************************
ALIGNLONG
DoWalls
; Check if FirstWall is still visible ---------------------------------
move.l Game_LevelPtr,a1 ; a1 = Pointer to Level array
move.w Level_NumWall(a1),d1 ;
subq.w #1,d1 ; d1 = Level_NumWall-1
move.l Game_WallZ,a4 ; a4 = Pointer to Wall_Z array
move.l Plyr_Z,d2 ; d2 = Plyr_Z
move.w Game_FirstWall,d0 ; d0 = Game_FirstWall
move.l (a4,d0.w*4),d3 ; d3 = Wall_Z[Game_FirstWall]
cmp.l d2,d3 ;
bgt.b .levcpl ; IF d3 <= d2
addq.w #1,d0 ; THEN Game_FirstWall += 1
move.w d0,Game_FirstWall ;
; Check if level is completed -----------------------------------------
.levcpl cmp.l #Flg_Normal,Game_Flags ; IF Game_Flags <> Flg_Normal
bne.b .chk1 ; THEN skip this bit
move.l (a4,d0.w*4),d3 ; d3 = Wall_Z[Game_FirstWall]
sub.l d2,d3 ; d3 = Wall_Z[FW]-Plyr_Z
cmp.l #RealZ,d3 ;
bge.b .chk1 ; IF d3 < RealZ
cmp.w d1,d0 ;
bne.b .chk1 ; AND Game_FirstWall = Level_NumWall-1
move.l #Flg_LevelDone,Game_Flags ; THEN level complete !!!
; Check if a new wall becomes visible ---------------------------------
.chk1 move.w Game_LastWall,d0 ; d0 = Game_LastWall
cmp.w d1,d0 ;
blt.b .chk2 ; IF Game_LastWall >= Level_NumWall-1
move.w d1,Game_LastWall ; THEN Game_LastWall = Level_NumWall-1
bra.b .Draw
.chk2 addq.w #1,d0 ; d0 = Game_LastWall+1
move.l (a4,d0.w*4),d1 ; d1 = Wall_Z[Game_LastWall+1]
add.l #ViewD,d2 ; d2 = Plyr_Z + ViewD
cmp.l d2,d1 ;
bge.b .Draw ; IF d1 < d2
move.w d0,Game_LastWall ; THEN Game_LastWall += 1
; Draw the visible walls back to front --------------------------------
.Draw
move.l #WallLut_X,a1 ;
move.l #WallLut_Y,a2 ;
move.l #WallLut_S,a3 ;
move.w Game_LastWall,d7 ;
move.w d7,d0 ; t=LastWall
sub.w Game_FirstWall,d7 ; d7=LastWall-FirstWall (loop counter)
sub.w #1,d7 ; d7=LastWall-FirstWall-1
bmi.b .First ;
.drwlop ; FOR (t=LastWall; t>=FirstWall-1; t--)
move.l (a4,d0.w*4),d1 ; d1 = Wall_Z[t]
sub.l Plyr_Z,d1 ; RelZ = Wall_Z[t] - Plyr_Z
movem.l d0/d1/d7/a0-a3,-(sp) ;
move.l (a1,d1.w*4),d2 ; BufferX
move.l (a2,d1.w*4),d3 ; BufferY
move.l (a3,d1.w*4),d4 ; Size
move.l Game_WallType,a1 ; a1 = Pointer to Wall_Type array
move.l #Type_Bitmap,a0 ;
move.w (a1,d0.w*2),d6 ; d6 = Wall_Type[t]
move.l (a0,d6.w*4),a0 ; SourcePtr = Type_Bitmap[Wall_Type[t]]
move.l RendCh,a1 ; BufferPtr
bsr.w ScaleWall ;
movem.l (sp)+,d0/d1/d7/a0-a3 ;
subq.w #1,d0 ;
dbf d7,.drwlop ; NEXT t
; Draw FirstWall and player -------------------------------------------
.First
move.l (a4,d0.w*4),d1 ; d1 = Wall_Z[t]
sub.l Plyr_Z,d1 ; RelZ = Wall_Z[t] - Plyr_Z
cmp.l #ViewD,d1 ; IF d1 < ViewD
bcs.b .visible ; THEN FirstWall is visible
bsr.w DrawPlayer ; ELSE DrawPlayer
bra.w .Done ; and leave !!!
.visible
move.l (a1,d1.w*4),d2 ; BufferX
move.l (a2,d1.w*4),d3 ; BufferY
move.l (a3,d1.w*4),d4 ; Size
move.l Game_WallType,a1 ; a1 = Pointer to Wall_Type array
move.l #Type_Bitmap,a0 ;
move.w (a1,d0.w*2),d6 ; d6 = Wall_Type[FirstWall]
move.l (a0,d6.w*4),a0 ; SourcePtr = Type_Bitmap[Wall_Type[FW]]
move.l RendCh,a1 ; BufferPtr
move.l d1,a4 ; save RelZ
move.l d6,a6 ; save Wall_Type[FirstWall]
cmp.l #RealZ,d1 ; IF d1 < RealZ
bge.b .else ;
bsr.w DrawPlayer ; DrawPlayer()
bsr.w ScaleWall ; ScaleWall()
bra.b .TstColl ; ELSE
.else bsr.w ScaleWall ; ScaleWall()
bsr.w DrawPlayer ; DrawPlayer()
; Test for collision --------------------------------------------------
.TstColl
cmp.l #Flg_Normal,Game_Flags ; IF Game_Flags <> Flg_Normal
bne.b .Done ; THEN skip collision check
move.l a4,d1 ; restore RelZ
move.l a6,d0 ; restore Wall_Type[FirstWall]
cmp.l #RealZ,d1 ; IF RelZ <= RealZ
bgt.b .Done ;
move.w Plyr_ZSpd,d2 ;
lsr.w #8,d2 ;
move.w #RealZ,d3 ;
sub.w d2,d3 ;
cmp.w d3,d1 ; AND RelZ >= (RealZ-Plyr_ZSpd/256)
blt.b .Done ;
bsr.b InHole ; AND InHole(Wall_Type[FirstWall])==0
bne.b .Done ;
move.l #Flg_Collision,Game_Flags ; THEN Collision !
sub.w #1,Plyr_Ships ; Plyr_Ships -= 1
; Finished ------------------------------------------------------------
.Done
rts
; *****************************************************************************
; InHole
; -----------------------------------------------------------------------------
; Inputs : d0.w = Type of wall
; Output : d0.l = 0 : Outside hole
; d0.l = 1 : Inside hole
; Description: Determines if ship is _completely_ inside the hole a wall.
; Notes : -
; Scratch : d0
; History : -
; *****************************************************************************
ALIGNLONG
InHole
movem.l d1-d4/a0-a1,-(sp) ; Save registers
lea Type_Hole,a0 ; Hole data
lea Coll_Bounds,a1 ; Collision bounds data
move.w Plyr_Frame,d3 ; Current player frame number
move.w Type_HoleX1(a0,d0.w*8),d2 ; IF (Plyr_X-Coll_BoundsX1)
move.w Plyr_X,d1 ; < Type_HoleX1[Type]
move.w Coll_BoundsX1(a1,d3.w*8),d4 ;
add.w d4,d1 ;
cmp.w d2,d1 ;
blt.b .Ret0 ; THEN return 0
move.w Type_HoleX2(a0,d0.w*8),d2 ; IF (Plyr_X+Coll_BoundsX2)
move.w Plyr_X,d1 ; > Type_HoleX2[Type]
move.w Coll_BoundsX2(a1,d3.w*8),d4 ;
add.w d4,d1 ;
cmp.w d2,d1 ;
bgt.b .Ret0 ; THEN return 0
move.w Type_HoleY1(a0,d0.w*8),d2 ; IF (Plyr_Y-Coll_BoundsY1)
move.w Plyr_Y,d1 ; < Type_HoleY1[Type]
move.w Coll_BoundsY1(a1,d3.w*8),d4 ;
add.w d4,d1 ;
cmp.w d2,d1 ;
blt.b .Ret0 ; THEN return 0
move.w Type_HoleY2(a0,d0.w*8),d2 ; IF (Plyr_Y+Coll_BoundsY2)
move.w Plyr_Y,d1 ; > Type_HoleY2[Type]
move.w Coll_BoundsY2(a1,d3.w*8),d4 ;
add.w d4,d1 ;
cmp.w d2,d1 ;
bgt.b .Ret0 ; THEN return 0
.Ret1 moveq #1,d0 ; Return 1
movem.l (sp)+,d1-d4/a0-a1 ; Restore registers
rts
.Ret0 moveq #0,d0 ; Return 0
movem.l (sp)+,d1-d4/a0-a1 ; Restore registers
rts
; *****************************************************************************
; DrawTunnel
; -----------------------------------------------------------------------------
; Inputs : -
; Outputs : -
; Description: Draws the tunnel into the chunky buffer.
; Notes : -
; Scratch : d0,d1,d7,a0,a1,a2
; Author : Matthijs Hollemans
; History : 24 Dec 1996
; 04 Jan 1997, Major speedup: writes longs instead of bytes.
; *****************************************************************************
ALIGNLONG
DrawTunnel
moveq #0,d0
move.w #160*128/4-1,d7 ; 20480 pixels
move.l RendCh,a0
move.l #txt,a1 ; Pointer to texture
move.l #TxtLut,a2 ; Pointer to texture LookUpTable
move.w Plyr_Scroll,d1
.loop move.w d1,d0 ; d0 = Scroll
add.w (a2)+,d0 ; d0 += Texture offset
move.b (a1,d0.l),d2 ; xxxxxxAA
lsl.w #8,d2 ; xxxxAAxx
move.w d1,d0 ; d0 = Scroll
add.w (a2)+,d0 ; d0 += Texture offset
move.b (a1,d0.l),d2 ; xxxxAABB
swap d2 ; AABBxxxx
move.w d1,d0 ; d0 = Scroll
add.w (a2)+,d0 ; d0 += Texture offset
move.b (a1,d0.l),d2 ; AABBxxCC
lsl.w #8,d2 ; AABBCCxx
move.w d1,d0 ; d0 = Scroll
add.w (a2)+,d0 ; d0 += Texture offset
move.b (a1,d0.l),d2 ; AABBCCDD
move.l d2,(a0)+ ; Store 4 pixels in chunky buffer
dbf d7,.loop
rts
; *****************************************************************************
; ScaleWall
; -----------------------------------------------------------------------------
; Inputs : a0 = SourcePtr
; a1 = BufferPtr
; d2.l = BufferX
; d3.l = BufferY
; d4.l = Destination Size (= width = height)
; d6.w = Walltype
; Output : -
; Description: Scales a 128x128 chunky image.
; Notes : o Performs clipping.
; o Does not perform mirroring.
; o Destination coordinates are allowed to be negative.
; o Colour 0 is transparent.
; Scratch : d0-d7/a0-a3/a5
; Author : Matthijs Hollemans
; History : 27 Dec 1996
; 04 Jan 1997, On some walls (WT_Left/Right/Up/Down) a lot of
; transparent pixels were scaled, wasting time.
; *****************************************************************************
ALIGNLONG
ScaleWall
; Determine step size -------------------------------------------------
move.l d4,d5 ; ClipW = ClipH = Destination Size
move.l #$8000,d0 ; XStep = SourceW << 8
divu d4,d0 ; XStep = (SourceW << 8) / DestW
andi.l #$ffff,d0 ; Get rid of remainder
move.l d0,d1 ; YStep = XStep
; Special type ? ------------------------------------------------------
cmp.w #WT_Left,d6 ; IF Walltype=WT_Left
bne.b .nolt ;
lsr.l #1,d4 ; ClipW /= 2
bra.b .Clip ; ENDIF
.nolt cmp.w #WT_Right,d6 ; IF Walltype=WT_Right
bne.b .nort ;
lsr.l #1,d4 ; ClipW / 2
move.l #CenterX,d2 ; BufferX = CenterX
bra.b .Clip ; ENDIF
.nort cmp.w #WT_Up,d6 ; IF Walltype=WT_Up
bne.b .noup ;
lsr.l #1,d5 ; ClipH / 2
bra.b .Clip ; ENDIF
.noup cmp.w #WT_Down,d6 ; IF Walltype=WT_Down
bne.b .Clip ; ClipH / 2
lsr.l #1,d5 ; BufferY = CenterY
move.l #CenterY,d3 ; ENDIF
; Clipping ------------------------------------------------------------
.Clip moveq #0,d6 ; SY = 0
cmp.l #ClipT,d3 ; IF BufferY < ClipT
bge.b .Bottom ;
move.l #ClipT,d6 ; d6 = ClipT
sub.l d3,d6 ; d6 = ClipT - BufferY
sub.l d6,d5 ; d5 -= ClipT - BufferY
mulu d1,d6 ; d6 = (ClipT - BufferY) * YStep
move.l #ClipT,d3 ; d3 = ClipT
.Bottom ; ENDIF
move.l d3,d7 ; d7 = BufferY
add.l d5,d7 ; d7 = BufferY + ClipH
cmp.l #ClipB,d7 ; IF (BufferY + ClipH) > ClipB
ble.b .Left ;
move.l #ClipB,d5 ; d5 = ClipB
sub.l d3,d5 ; d5 = ClipB - BufferY
addq.l #1,d5 ; d5 = ClipB - BufferY + 1
.Left ; ENDIF
mulu #BufferW,d3 ; d3 = BufferY * BufferW
add.l d3,a1 ; a1 += BufferY * BufferW
moveq #0,d3 ; StartSX = 0
cmp.l #ClipL,d2 ; IF BufferX < ClipL
bge.b .Right ;
move.l #ClipL,d3 ; d3 = ClipL
sub.l d2,d3 ; d3 = ClipL - BufferX
sub.l d3,d4 ; d4 -= (ClipL - BufferX)
mulu d0,d3 ; d3 = (ClipL - BufferX) * XStep
move.l #ClipL,d2 ; d2 = ClipL
.Right ; ENDIF
move.l d2,d7 ; d7 = BufferX
add.l d4,d7 ; d7 = BufferX + ClipW
cmp.l #ClipR,d7 ; IF (BufferX + ClipW) > ClipR
ble.b .ClpEnd ;
move.l #ClipR,d4 ; d4 = ClipR
sub.l d2,d4 ; d4 = ClipR - BufferX
addq.l #1,d4 ; d4 = ClipR - BufferX + 1
.ClpEnd ; ENDIF
add.l d2,a1 ; a1 += BufferX
move.l #BufferW,a3 ; a3 = BufferW
sub.l d4,a3 ; a3 = BufferW - ClipW
subq.l #1,d4 ; ClipW-1
bmi.b .Done ; IF ClipW < 0 THEN Done
subq.l #1,d5 ; ClipH-1
bmi.b .Done ; IF ClipH < 0 THEN Done
move.l d3,a5 ; a5 = StartSX
; Scaling -------------------------------------------------------------
; a0 = SourcePtr, a1 = BufferPtr, a2 = SourceLoop, a3 = BufferStep
; a5 = StartSX
; d0 = XStep, d1 = YStep, d2 = SX (only in ColLoop)
; d3 = scratch, d4 = ColLoop counter backup
; d5 = RowLoop counter, d6 = SY, d7 = ColLoop counter
.RowLoop ; FOR (i=0; i < ClipH; i++)
move.l d6,d2 ; d2 = SY
movea.l a0,a2 ; a2 = SourcePtr
lsr.l #1,d2 ; d2 = (SY >> 8)
andi.l #$ffffff80,d2 ; d2 = (SY >> 8) * SourceW
add.l d2,a2 ; a2 = SourcePtr + (SY >> 8)*SourceW
move.l a5,d2 ; d2 = StartSX
move.l d4,d7 ; FOR (j=0; j < ClipW; j++)
.ColLoop ;
move.l d2,d3 ;
lsr.l #8,d3 ; d3 = SX >> 8
add.l d0,d2 ; d2 += XStep
move.b (a2,d3.w),d3 ; d3 = *(SourceLoop + (SX >> 8))
beq.b .NxtCol ; IF d3 == 0 THEN don't draw
move.b d3,(a1) ; *BufferPtr = d3
.NxtCol addq.l #1,a1 ; BufferPtr += 1
dbf d7,.ColLoop ; ENDFOR
adda.l a3,a1 ; a1 += BufferStep
add.l d1,d6 ; d6 += YStep
dbf d5,.RowLoop ; ENDFOR
; Finished ------------------------------------------------------------
.Done
rts
; *****************************************************************************
; MyVBLHandler
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Custom VBL interrupt handler. Takes care of timers and stuff.
; Notes : Called from int3.
; Scratch : -
; Author : -
; History : -
; *****************************************************************************
MyVBLHandler
; Toggle --------------------------------------------------------------
move.l ToggleCnt,d0 ; ToggleCnt += 1
add.l #1,d0 ;
cmp.l #20,d0 ; IF ToggleCnt > 20
blt.b .notogl ;
bchg #0,Toggle ; Toggle
moveq #0,d0 ; ToggleCnt=0
.notogl move.l d0,ToggleCnt ; ENDIF
; RealTime ------------------------------------------------------------
add.l #1,RealTimeCnt ; RealTimeCnt += 1
; Timers --------------------------------------------------------------
cmp.l #Flg_Normal,Game_Flags ; IF Flg_Normal
bne.b .spcial ;
move.l #0,FlgTimer ; THEN FlgTimer = 0
sub.l #1,Plyr_Time ; Plyr_Time -= 1
bra.b .tstcol ;
.spcial add.l #1,FlgTimer ; ELSE FlgTimer += 1
.tstcol cmp.l #Flg_Collision,Game_Flags ; IF Flg_Collision
bne.b .Coll ;
sub.l #1,Plyr_Time ; THEN Plyr_Time -= 1
; Collision Fade ------------------------------------------------------
.Coll
cmp.l #Flg_Collision,Game_Flags ; IF not collision
beq.b .coll1 ;
cmp.l #Flg_RaceOver,Game_Flags ; OR race over
bne.b .Done ; THEN skip this part
.coll1 cmp.l #1,FlgTimer ; IF FlgTimer = 1
blt.b .Done ;
bgt.b .coll0 ;
move.l RendCop,a0 ;
add.l #CopCol-Cop,a0 ;
move.l #WhitePal,a1 ;
bsr.w SetPal24 ; Make screen totally white
move.l #WhitePal,a0 ;
move.l #TempPal,a1 ;
bsr.w CopyPal24 ;
move.b #5,d0 ;
bsr.w InitXFade ; Initialise crossfade
bra.b .Done ;
.coll0 move.l #TempPal,a0 ; ELSEIF FlgTimer > 1
move.l #GamePal,a1 ;
bsr.w XFade ;
move.l RendCop,a0 ; Crossfade white to
add.l #CopCol-Cop,a0 ; original game palette
move.l #TempPal,a1 ;
bsr.w SetPal24 ; ENDIF
; Finished ------------------------------------------------------------
.Done
rts
; *****************************************************************************
; LoadScores
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Stores default values in BestTimes and BestNames arrays.
; Notes : -
; Scratch : All
; Author : Matthijs Hollemans
; History : 23 Jan 1997
; *****************************************************************************
ALIGNLONG
LoadScores
lea BestTimes,a0 ;
lea BestNames,a1 ;
move.w #9-1,d7 ;
.loop0 move.l #29950,(a0)+ ; Write default time
move.l #"NOBO",(a1)+ ; }
move.l #"DY ",(a1)+ ; }- Write default name
move.l #$20202000,(a1)+ ; }
dbf d7,.loop0 ;
rts
; =============================================================================
;
; S U B R O U T I N E S
;
; =============================================================================
; *****************************************************************************
; PPutChr
; -----------------------------------------------------------------------------
; Inputs : a1 = Pointer to first bitplane
; d0.l = ASCII character
; Output : -
; Description: Planar Put Character.
; Notes : -
; Scratch : d0,d1,d2,d7,a2,a3,a5
; Author : Matthijs Hollemans
; History : 06 Jan 1997
; *****************************************************************************
ALIGNLONG
PPutChr
lea IntroFont,a2 ; a2 = Pointer to gfx
sub.l #32,d0 ; Convert ASCII
move.l d0,d1 ; d0 = Offset for plane 7 gfx
add.w #1024,d1 ; d1 = Offset for plane 8 gfx
move.l a1,a5 ;
add.l #20480,a5 ; a5 = Pointer to plane 8
move.l a1,a3 ; a3 = Pointer to plane 7
move.w #16-1,d7 ; Draw 16 lines
.copy move.b (a2,d0.w),(a3) ; Write to plane 7
move.b (a2,d1.w),(a5) ; Write to plane 8
add.l #40,a3 ; Next line in plane 7
add.l #40,a5 ; Next line in plane 8
add.l #64,a2 ; Next line in gfx
dbf d7,.copy ; Draw next line
rts
; *****************************************************************************
; PPutStr
; -----------------------------------------------------------------------------
; Inputs : a0 = Pointer to null-terminated string
; a1 = Pointer to first bitplane
; Output : -
; Description: Planar Put String.
; Notes : -
; Scratch : All
; Author : Matthijs Hollemans
; History : 06 Jan 1997
; *****************************************************************************
ALIGNLONG
PPutStr
moveq #0,d0
.loop move.b (a0)+,d0 ; Read next character
beq.b .Done ; NULL byte ? then we're done
bsr.b PPutChr ; Write character
addq.l #1,a1 ; Next position on screen
bra.b .loop ; Next character
.Done rts ; Finished
; *****************************************************************************
; CPutStr
; -----------------------------------------------------------------------------
; Inputs : a0 = Pointer to null-terminated string
; a1 = Pointer to chunky buffer.
; Output : -
; Description: Chunky Put String
; Notes : -
; Scratch : d0,d1,d2,d6,d7,a1,a2,a3
; Author : Matthijs Hollemans
; History : 08 Jan 1996
; *****************************************************************************
ALIGNLONG
CPutStr
moveq #0,d0
.loop move.b (a0)+,d0 ; Read next character
beq.b .Done ; NULL byte ? then we're done
bsr.b CPutChr ; Write character
addq.l #8,a1 ; Next position on screen
bra.b .loop ; Next character
.Done rts ; Finished
; *****************************************************************************
; CPutChr
; -----------------------------------------------------------------------------
; Inputs : a1 = Pointer to chunky buffer
; d0.l = ASCII character
; Output : -
; Description: Chunky Put Character.
; Notes : -
; Scratch : d0,d1,d2,d6,d7,a2,a3
; Author : Matthijs Hollemans
; History : 08 Jan 1996
; *****************************************************************************
ALIGNLONG
CPutChr
lea ChunkyFont,a2 ; a2 = Pointer to gfx
sub.l #32,d0 ; Convert ASCII
move.l d0,d1 ;
lsl.l #3,d1 ; d1 = Offset for gfx
add.l d1,a2 ; a2 += offset
move.l a1,a3 ; a3 = Pointer to chunkybuffer
move.w #7,d6 ; }_ 8x8 character
.y move.w #7,d7 ; }
.x move.b (a2),d2 ; Read gfx byte
beq.b .skip ; 0 ? Then transparent, skip write
move.b d2,(a3) ; Write gfx byte
.skip add.l #1,a3 ; Next pixel in chunky buffer
add.l #1,a2 ; Next pixel in gfx
dbf d7,.x ;
add.l #BufferW-8,a3 ; Next row in chunky buffer
add.l #512-8,a2 ; Next row in gfx
dbf d6,.y ;
rts
; *****************************************************************************
; CWriteTime, PWriteTime
; -----------------------------------------------------------------------------
; Inputs : a4.l = Offset in chunky buffer
; d5.l = Time (in ticks)
; Output : -
; Description: CWriteTime: writes time as M:SS in chunky buffer.
; PWriteTime: writes time as M:SS on 2-bitplane screen.
; Notes : -
; Scratch : All
; Author : -
; History : -
; *****************************************************************************
CalcTime
divu.w #50,d5 ; Total secs = Ticks / 50
and.l #$ffff,d5 ; kill remainder
divu.w #60,d5 ; Min = Total secs / 60
move.l d5,d3 ;
and.l #$f,d5 ; kill remainder
swap d3 ; Sec = Total secs MOD 60
and.l #$ffff,d3 ; kill msw
divu #10,d3 ;
move.l d3,d4 ;
swap d4 ; Get second
and.l #$f,d3 ;
and.l #$f,d4 ;
rts
CWriteTime
bsr.b CalcTime ; Calculate time
CPUTNUM d5,a4 ; X:xx
addq.l #8,a4 ;
CPUTCHR #58,a4 ; :
addq.l #8,a4 ;
CPUTNUM d3,a4 ; x:Xx
addq.l #8,a4 ;
CPUTNUM d4,a4 ; x:xX
rts
PWriteTime
bsr.w CalcTime ; Calculate time
PPUTNUM d5,a4 ; X:xx
addq.l #1,a4 ;
PPUTCHR #58,a4 ; :
addq.l #1,a4 ;
PPUTNUM d3,a4 ; x:Xx
addq.l #1,a4 ;
PPUTNUM d4,a4 ; x:xX
rts
; *****************************************************************************
; SetPal24
; -----------------------------------------------------------------------------
; Inputs : a0 = Pointer to coplist colors
; a1 = Palette
; Output : -
; Description: Copies a 24-bit 256-colour palette into a coplist.
; Notes : Palette has to be ordered like this:
; $00RrGgBb,$00RrGgBb,...,$00RrGgBb
; Scratch : d6,d7,a0,a1
; Author : Matthijs Hollemans
; History : 4 Jan 1996
; *****************************************************************************
ALIGNLONG
SetPal24
add.l #6,a0 ;
move.w #8-1,d6 ; Set 8 banks
.loop0 move.w #32-1,d7 ; Set 32 colour registers
.loop1 move.l (a1)+,d0 ; d0 = 00RrGgBb
move.w d0,d1 ; d1 = GgBb
lsr.w #8,d1 ; d1 = 00Gg
and.w #$f0,d1 ; d1 = 00G0
move.w d0,d2 ; d2 = GgBb
and.w #$f0,d2 ; d2 = 00B0
lsr.w #4,d2 ; d2 = 000B
or.w d1,d2 ; d2 = 00GB
move.l d0,d1 ; d1 = 00RrGgBb
swap d1 ; d1 = GgBb00Rr
and.w #$f0,d1 ; d1 = 00R0
lsl.w #4,d1 ; d1 = 0R00
or.w d1,d2 ; d2 = 0RGB
move.w d2,(a0) ; Write high 12-bits in copperlist
move.w d0,d1 ; d1 = GgBb
and.w #$f00,d1 ; d1 = 0g00
lsr.w #4,d1 ; d1 = 00g0
move.w d0,d2 ; d2 = GgBb
and.w #$f,d2 ; d2 = 000b
or.w d1,d2 ; d2 = 00gb
swap d0 ; d0 = GgBb00Rr
and.w #$f,d0 ; d0 = 000r
lsl.w #8,d0 ; d0 = 0r00
or.w d0,d2 ; d2 = 0rgb
move.w d2,132(a0) ; Write low 12-bits in copperlist
add.l #4,a0 ; Next colour
dbf d7,.loop1 ;
add.l #128+4+4,a0 ;
dbf d6,.loop0 ;
rts ;
; *****************************************************************************
; CopyPal24
; -----------------------------------------------------------------------------
; Inputs : a0 = Source palette
; a1 = Destination palette
; Output : -
; Description: Copies 24-bit source palette into 24-bit destination palette.
; Notes : -
; Scratch : All
; Author : Matthijs Hollemans
; History : 23 Jan 1997
; *****************************************************************************
CopyPal24
move.l #256-1,d7 ; 256 colours
.loop move.l (a0)+,(a1)+ ; Copy 24-bit colour
dbf d7,.loop ;
rts
; *****************************************************************************
; InitXFade
; -----------------------------------------------------------------------------
; Inputs : d0.b = Stepsize (positive value)
; Output : -
; Description: Initialises XFade.
; Notes : Call once before calling XFade.
; Scratch : -
; Author : Matthijs Hollemans
; History : 23 Jan 1997
; *****************************************************************************
InitXFade
and.l #$ff,d0 ; Extend d0 to long (unsigned)
move.b d0,XFadeStep ; XFadeStep = Stepsize
move.l #$ff,d1 ;
divu.w d0,d1 ; XFadeCount = 255 / Stepsize
move.w d1,XFadeCount ;
rts
; *****************************************************************************
; XFade
; -----------------------------------------------------------------------------
; Inputs : a0 = Source palette
; a1 = Destination palette
; Output : -
; Description: Fades 24-bit source palette to 24-bit destination palette.
; Notes : If XFadeCount is negative, then fading is ready and the
; routine exits. Start a new fade by calling InitXFade.
; Scratch : All
; Author : Matthijs Hollemans
; History : 23 Jan 1997
; *****************************************************************************
ALIGNLONG
XFade
tst.w XFadeCount ; IF XFadeCount < 0
bmi.b .Done ; THEN xfade is ready
move.b XFadeStep,d3 ; d3 = Step
ext.w d3 ; Extend d3 to word size !
move.b d3,d4 ;
neg.b d4 ; d4 = -Step
ext.w d4 ; Extend d4 to word size !
move.l #256-1,d7 ; Process 256 colours
.loop addq.l #1,a0 ; }_ Skip first byte
addq.l #1,a1 ; }
moveq #3-1,d6 ; Loop 3 times (r,g and b)
.rgb moveq #0,d0 ; }_ Clear registers
move.l d0,d2 ; }
move.b (a0),d0 ; d0 = Source component
move.b (a1)+,d1 ; d1 = Dest component
move.b d1,d2 ;
sub.w d0,d2 ; d2 = Dest-Source (word!!!)
cmp.w d3,d2 ; IF d2 > Step
ble.b .0 ;
add.b d3,d0 ; Source += Step
bra.b .write ;
.0 cmp.w d4,d2 ; ELSEIF d2 < -Step
bge.b .1 ;
sub.b d3,d0 ; Source -= Step
bra.b .write ;
.1 move.b d1,d0 ; ELSE Source = Dest
.write move.b d0,(a0)+ ; Write new source component
dbf d6,.rgb ;
dbf d7,.loop ;
sub.w #1,XFadeCount ; XFadeCount -= 1
.Done ;
rts ;
XFadeCount dc.w 0
XFadeStep dc.b 0
; *****************************************************************************
; GetJoy1
; -----------------------------------------------------------------------------
; Inputs : -
; Outputs : -
; Description: Reads position of joystick 1.
; Notes : Results in Joy1Up, Joy1Down, Joy1Left, Joy1Right, Joy1Fire.
; Scratch : -
; Author : Matthijs Hollemans
; History : 24 Dec 1996
; *****************************************************************************
ALIGNLONG
GetJoy1 movem.l d0/d1,-(sp)
move.w $dff00c,d0 ; JOY1DAT
btst #1,d0
sne Joy1Right
btst #9,d0
sne Joy1Left
move.w d0,d1
lsr.w #1,d1
eor.w d0,d1
btst #0,d1
sne Joy1Down
btst #8,d1
sne Joy1Up
moveq #0,d0
btst.b #7,$bfe001 ; CIA-A PRA
seq Joy1Fire
movem.l (sp)+,d0/d1
rts
; *****************************************************************************
; WaitVBL
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Waits for vertical blank.
; Notes : -
; Scratch : None
; Author : -
; History : -
; *****************************************************************************
ALIGNLONG
WaitVBL move.l d0,-(sp)
move.b $bfe801,d0
.wait cmp.b $bfe801,d0
beq.b .wait
move.l (sp)+,d0
rts
; *****************************************************************************
; GetKey
; -----------------------------------------------------------------------------
; Inputs : -
; Output : KeyState and KeyRaw
; Description: Gets keyboard input
; Notes : -
; Scratch : d0,d1
; Author : Fabio Bizetti
; History : 11 Jan 1997, modified by Matthijs Hollemans
; *****************************************************************************
GetKey
move.w $dff01c,d1 ; Save INTENA
or.w #$c000,d1 ;
move.w #$7fff,$dff09a ; Disable all interrupts
moveq #0,d0 ;
move.b $bfec01,d0 ; Get byte from CIA-A serial port
bset.b #6,$bfee01 ; Set serial port to output
move.b #$40,$bfe401 ; }_ CIA-A TimerA = 64
move.b #$00,$bfe501 ; }
move.b #$51,$bfee01 ; Handshake
tst.b $bfed01 ;
tst.b $bfed01 ;
.Wait btst.b #0,$bfed01 ; }_ Wait for TimerA to finish
beq.b .Wait ; }
bclr.b #6,$bfee01 ; Set serial port to input
not.b d0 ; Datalines are low active
ror.b #1,d0 ; Bits are sent as 6-5-4-3-2-1-0-7
bpl.b .Down ; IF Key was released
move.b #KEY_NONE,KeyState ; KeyState = KEY_NONE
move.b d0,KeyRaw ; KeyRaw = new key with bit 7 set!
bra.b .Done ; ENDIF
.Down cmp.b KeyRaw,d0 ; IF old key == new key
bne.b .New ;
move.b #KEY_REPEAT,KeyState ; KeyState = KEY_REPEAT
bra.b .Done ; ENDIF
.New move.b d0,KeyRaw ; KeyRaw = new key
move.b #KEY_NEW,KeyState ; KeyState = KEY_NEW
.Done move.w d1,$dff09a ; Restore interrupts
rts ;
; *****************************************************************************
; GetStr
; -----------------------------------------------------------------------------
; Inputs : -
; Output : -
; Description: Gets string input from user and stores it in Plyr_Name.
; Notes : Could rewrite this to be somewhat more universal, but then
; again, why bother ;)
; Scratch : -
; Author : Matthijs Hollemans
; History : 21 Jan 1997
; *****************************************************************************
GetStr
movem.l d0-d7/a0-a6,-(sp) ; Save registers
lea Plyr_Name,a0 ; Destination address
move.l a0,a1 ; Store pointer
lea Raw2ASCII,a2 ; Translation table
move.b #0,d7 ; Size = 0
move.l #388*40+25,d6 ; Start position on screen
PPUTCHR #94,d6 ; Write cursor
.loop bsr.w WaitVBL ; REPEAT
bsr.w GetKey ; Read key
cmp.b #KEY_NEW,KeyState ;
bne.b .loop ; UNTIL KeyState = KEY_NEW
cmp.b #KEY_ENTER,KeyRaw ; IF KeyRaw = KEY_ENTER
bne.b .noent ;
move.b #0,(a1) ; Add NULL-character to end of string
bra.w .Done ; Finished
.noent cmp.b #KEY_ESC,KeyRaw ; ELSEIF KeyRaw = KEY_ESC
bne.b .noesc ;
move.b #0,(a0) ; NULL-character at start of string
bra.w .Done ; Finished
.noesc cmp.b #KEY_BACKSPACE,KeyRaw ; ELSEIF KeyRaw = KEY_BACKSPACE
bne.b .nobs ;
tst.b d7 ; IF Size > 0
ble.b .endif ;
subq.b #1,d7 ; Size -= 1
subq.b #1,d6 ; Position -= 1
subq.l #1,a1 ; Decrease string pointer
bra.b .endif ; ENDIF
.nobs cmp.b #$40,KeyRaw ; ELSEIF (KeyRaw <= $40)
bgt.b .endif ;
cmp.b #$10,KeyRaw ; AND (KeyRaw >= $10)
blt.b .endif ;
cmp.b #MaxStrLen,d7 ; IF Size = MaxStrLen
bge.b .endif ; THEN skip this part
moveq #0,d1 ;
move.b KeyRaw,d1 ; Convert Raw to ASCII
move.b (a2,d1.w),d1 ;
beq.b .endif ; IF ASCII=0 THEN illegal key
move.b d1,(a1)+ ; Write ASCII value in string
PPUTCHR d1,d6 ; Write ASCII value on screen
addq.b #1,d7 ; Size += 1
addq.b #1,d6 ; Position += 1
.endif move.l d6,d5 ; ENDIF
PPUTCHR #94,d5 ; Write cursor
add.l #1,d5 ;
PPUTCHR #32,d5 ; Write empty space behind cursor
PPUTCHR #95,#389*40-3 ; Restore frame ;)
bra.w .loop ;
.Done ; Finished
movem.l (sp)+,d0-d7/a0-a6 ; Restore registers
rts ;
; =============================================================================
;
; B L I T T E R S C R E E N
;
; =============================================================================
ALIGNLONG
timer dc.l 0 ; some vbl-timers...
timer2 dc.l 0
oldtimer dc.l 0
show2 equ 0 ; equ 1 show rastertiming of blitterpasses
; *****************************************************************************
; Macro's
; *****************************************************************************
waitblt MACRO ; Hardware WaitBlit()
btst #6,$dff002 ; Old blitters said to have bug...
waitblt\@: ;
btst #6,$dff002 ;
bne waitblt\@ ;
ENDM ;
; *****************************************************************************
; mkbltscr
; -----------------------------------------------------------------------------
; Inputs : a0 = Copperlist
; a1 = Screen
; Output :
; Description: Makes copperlist for blitterscreen.
; Notes : -
; History : ??.??.1995, Jurgen "Rally" Fischer
; 26.12.1996, Matthijs Hollemans
; *****************************************************************************
ALIGNLONG
mkbltscr:
; Write bitplane pointers in copperlist header ------------------------
move.l #CopBpl,a2 ; a2=Position in copperlist header
move.l a1,d0 ; d0=Screen address
move.w #8-1,d7 ; Write 8 bitplanes
.mkbpl swap d0 ;
move.w d0,2(a2) ;
swap d0 ;
move.w d0,6(a2) ;
addq.l #8,a2 ; Next position in copperlist
add.l #320*128/8,d0 ; Next bitplane
dbf d7,.mkbpl ;
; Copy copperlist header into chipmem ---------------------------------
move.l #Cop,a2 ;
move.w #CopEnd-Cop-1,d7 ;
.cpycop move.b (a2)+,(a0)+ ;
dbf d7,.cpycop ;
; 2xY stuff -----------------------------------------------------------
move.l chipmem,a2 ;
add.l #sprbuf,a2 ; a2=Sprite buffer
move.l a1,d0 ; d0=Screen
move.l #40,d2 ; YStart
move.l #128,d3 ; Number of lines
move.l #40*128,d4 ; Planesize (in bytes)
move.l #40,d5 ; Linesize (in bytes)
jsr mk2xY ;
; End copperlist (feel free to add your own copper stuff) ------------
move.l #$fffffffe,(a0)+
rts
; ****************************************************************************
; int3
; ----------------------------------------------------------------------------
; Hardware-hack interrupt handler
; ****************************************************************************
ALIGNLONG
int3:
btst #6,$dff01f ; BLIT3 set ?
beq.b nobltint ; Nope, interrupt not caused by blitter
bltint:
move.w #$0040,$dff09c ; Clear BLIT3
movem.l d0-d1/a5/a6,-(sp)
move.l #$dff000,a5
move.l bltpc(pc),a6 ; a6 = "program counter" for blitlist
IFNE show2
move.w #$0ff,$dff180 ;blt reload
ENDC
bltsetreg:
move.l (a6)+,d0
move.w d0,d1
beq.b bltintend
swap d0
move.w d0,0(a5,d1.w)
cmp.w #$5e,d1
beq.b bltstarted
cmp.w #$58,d1
bne.b bltsetreg
* ---
bltstarted:
move.l a6,bltpc
movem.l (sp)+,d0-d1/a5/a6
IFNE show2
move.w #$800,$dff180 ;blt works
ENDC
rte
bltintend:
clr.w bltbsy
movem.l (sp)+,d0-d1/a5/a6
IFNE show2
move.w #$000,$dff180 ;blt rdy
ENDC
rte
nobltint: ; No blitter interrupt
btst #5,$dff01f ; Was it a VBL interrupt?
bne.b vblint
btst #4,$dff01f ; Or a copper interrupt ?
bne.b copint
* huh ? ; Fuckup !
move.w #$3fff,$dff09c ; kill all requests to avoid(?) delirium
rte
ALIGNLONG
bltpc dc.l 0 ;pointer to blitterinstructions to be done
bltbsy dc.w 0 ;this is 0 if all blitter-passes are done
ALIGNLONG
vblint:
move.w #$0020,$dff09c ; remove vblank interrupt
movem.l d0-d7/a0-a6,-(sp)
move.l customvbl,a0
jsr (a0) ; CUSTOM ROUTINE HERE!
add.l #1,timer
add.l #1,timer2
move.w #$0020,$dff09c
movem.l (sp)+,d0-d7/a0-a6
rte
copint: ;theoretically you never get here... copints are disabled ;)
move.w #$0010,$dff09c ; remove copper interrupt
rte
customvbl dc.l MyVBLHandler ; Pointer to custom vblank routine
; *****************************************************************************
; mk2xY
; -----------------------------------------------------------------------------
; Inputs : a0 = Copperlist
; a2 = Sprite Buffer (size = 312*4*2*8)
; d0.l = Plane0
; d2 = Ystart
; d3 = Number of lines (0-127)
; d4.l = Planesize
; d5 = Linesize
; Output : -
; Description: Make a special 2x2 or 2x1 screen, needed for c2bs.
; Notes : All buffers in CHIP mem.
; 2x2 or 2x1 depends on modulo/doublescan-bit in coplist header.
; Make sure sprites are 64-bit (fmode 3), highest priority and
; choose the spritebank that has got a dark color at offset 1
; (eg. col 1, 17, 33, ...).
; History : 1995, Jurgen "Rally" Fischer
; *****************************************************************************
ALIGNLONG
mfpoffs dc.l 0 ;not used by caller
mfloffs dc.l 0
mk2xY:
jsr mspr ;gen cover-sprites in (a2)+ and copmoves in (a0)+
* PLANES
movem.l d0-d7/a1-a6,-(sp) ;a0=(ptr)copl
move.l d4,mfpoffs
ext.l d5
move.l d5,mfloffs
* gen planeptr moves
movem.l d3/d0,-(sp)
move.w #$00e0,d3
move.w #4-1,d7
mf256genhi:
move.w d3,(a0)+
addq.w #2,d3
move.l d0,(a0)+ ;store hiwd ! -2(a0)
move.w d3,-2(a0)
addq.w #2,d3
move.w d0,(a0)+ ;store lowd
;every 2nd plane same data
move.w d3,(a0)+
addq.w #2,d3
move.l d0,(a0)+ ;store hiwd ! -2(a0)
move.w d3,-2(a0)
addq.w #2,d3
move.w d0,(a0)+ ;store lowd
add.l mfpoffs,d0
dbra d7,mf256genhi
* end gen ptrs
movem.l (sp)+,d3/d0
and.l #$ff,d2
sub.b #1,d2
ror.l #8,d2 ;sub #1: prev line
move.l #$00e1fffe,d4
or.l d2,d4 ;WAS: 00df
*
move.w d3,d5
subq.w #1,d5
mf256yanz:
move.l #$1020010,d7
move.w #2-1,d6
mf256do2:
move.l d4,(a0)+
add.l #$01000000,d4 ;cwait
move.l d7,(a0)+
eor.l #$00000031,d7 ;horiz shift
; ^---- 3: 1 -> 2 -> 1 -> 2 ....
dbra d6,mf256do2
add.l mfloffs,d0
dbra d5,mf256yanz
movem.l (sp)+,d0-d7/a1-a6 ;a0=(ptr)copl
rts
; ****************************************************************************
; mspr
; ----------------------------------------------------------------------------
; Inputs : a0 = Copperlist
; a2 = Sprite Buffer (coplist: FMODE=$F, $dff104=$003f)
; Output : -
; Description: Sprites that mask out doubleplane-data-rubbish.
; Notes : mksprites into sprbuf=(a2)+ and according coppermoves in (a0)+
; History : 1995, Jurgen "Rally" Fischer.
; ***************************************************************************
ALIGNLONG
mspr:
movem.l d0-d7/a1-a6,-(sp) ;no a0! coz *copl
move.l #$00968020,(a0)+ ;rehash sprites (for safety)
lea mf2sprdat,a1
move.l a2,d0
add.l #15,d0
and.l #$fffffff0,d0
move.l d0,a2 ;align
move.w #$0120,d1 ;spr0pth
move.w #8-1,d7 ;sprcnt
mf2mkspr:
* cmoves for sprptr in copl
move.l a2,d0
move.w d1,(a0)+
addq.w #2,d1 ;hiptr -> loptr
swap d0
move.w d0,(a0)+
swap d0 ;hiwd
move.w d1,(a0)+
addq.w #2,d1 ;next sprptr
move.w d0,(a0)+
* make sprbuf
move.l (a1)+,(a2)+ ;ctl1
move.l #0,(a2)+ ;dummy for 64bit fetchmode
move.l (a1)+,(a2)+ ;ctl2
move.l #0,(a2)+ ;dummy for 64bit fetchmode
move.l (a1)+,d2
move.l (a1)+,d3
move.l d2,d4
ror.l #1,d4
move.l d3,d5
ror.l #1,d5
move.w #128-1,d6
mf2mksprdat:
move.l d2,(a2)+
move.l d2,(a2)+
move.l d3,(a2)+
move.l d3,(a2)+
;2nd line
move.l d4,(a2)+
move.l d4,(a2)+
move.l d5,(a2)+
move.l d5,(a2)+ ;2nd plane
dbra d6,mf2mksprdat
move.l #$0,(a2)+
move.l #$0,(a2)+
move.l #$0,(a2)+
move.l #$0,(a2)+
dbra d7,mf2mkspr
movem.l (sp)+,d0-d7/a1-a6 ;ohne a0! weil *copl
rts
* ctl 1, ctl 2, plane 0, plane 1 (to be lsr'd for 2nd line)
mf2sprdat:
dc.l $28400000,$a7020000,$aaaaaaaa,$00000000
dc.l $28600000,$a7020000,$aaaaaaaa,$00000000 ;1 & 2 nonattached, col 1 :)
dc.l $28800000,$a7020000,$aaaaaaaa,$00000000
dc.l $28800000,$a7820000,$00000000,$00000000
dc.l $28a00000,$a7020000,$aaaaaaaa,$00000000
dc.l $28a00000,$a7820000,$00000000,$00000000
dc.l $28c00000,$a7020000,$aaaaaaaa,$00000000
dc.l $28c00000,$a7820000,$00000000,$00000000
; ****************************************************************************
; c2bs
; ----------------------------------------------------------------------------
; Inputs : a0 = Chunky Buffer
; a1 = Screen
; a2 = Pass Buffer (half size of chunky buffer)
; a3 = Scramble Buffer (at size of chunky buffer)
; a6 = Blitter-list Buffer (size less than 2k)
; d0.l = Number of chunky pixels
; d1.l = Plane Offset (number of bytes between planes)
; Outputs : -
; Description: Non-scrambled chunky-to-planar conversion.
; Not really C2P, destination is special 2x2 or 2x1 screen.
; Notes : All buffers in CHIP memory, except Blitter-list (a6).
; History : 1995, Jurgen "Rally" Fischer.
; ****************************************************************************
ALIGNLONG
c2bs:
tst.w bltbsy
bne.b c2bs ;for the very unlikely case your mapping-
;engine renders faster than blitterc2p ;)
move.l a6,bltpc ;handler starts at bltpc
movem.l d0-d1/a0-a3,-(sp)
move.l a3,a4 ;well....
*** init values
move.l #$04000096,(a6)+
move.l #$80400096,(a6)+
move.l #$ffff0044,(a6)+
move.l #$ffff0046,(a6)+
*** scrambling passes
;subpass 1
lea (a0),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea 4(a0),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea (a4),a3
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$8de40040,(a6)+
move.l #$00000042,(a6)+
move.l #$00ff0070,(a6)+ ;cdat
move.l #$00060064,(a6)+
move.l #$00060062,(a6)+ ;a/b mod
move.l #$00060066,(a6)+ ;d mod
move.l d0,d6
lsr.l #3,d6 ;1/4 of scr, words => /8
move.w d6,(a6)+
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
;subpass2
lea 2(a0),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea 6(a0),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea 2(a4),a3
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$8de40040,(a6)+
move.l #$00000042,(a6)+
move.l #$00ff0070,(a6)+ ;cdat
move.l #$00060064,(a6)+
move.l #$00060062,(a6)+ ;a/b mod
move.l #$00060066,(a6)+ ;d mod
move.l d0,d6
lsr.l #3,d6 ;1/4 of scr, words => /8
move.w d6,(a6)+
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
;subpass 3
lea -4(a0,d0.l),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea -8(a0,d0.l),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea -4(a4,d0.l),a3
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$8de40040,(a6)+
move.l #$00020042,(a6)+
move.l #$ff000070,(a6)+ ;cdat
move.l #$00060064,(a6)+
move.l #$00060062,(a6)+ ;a/b mod
move.l #$00060066,(a6)+ ;d mod
move.l d0,d6
lsr.l #3,d6 ;1/4 of scr, words => /8
move.w d6,(a6)+
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
;subpass 4
lea -2(a0,d0.l),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea -6(a0,d0.l),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea -2(a4,d0.l),a3
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$8de40040,(a6)+
move.l #$00020042,(a6)+
move.l #$ff000070,(a6)+ ;cdat
move.l #$00060064,(a6)+
move.l #$00060062,(a6)+ ;a/b mod
move.l #$00060066,(a6)+ ;d mod
move.l d0,d6
lsr.l #3,d6 ;1/4 of scr, words => /8
move.w d6,(a6)+
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
***
movem.l (sp)+,d0-d1/a0-a3
move.l a3,a0 ;scrambled data is now there
*** init values
move.l #$04000096,(a6)+
move.l #$80400096,(a6)+
move.l #$ffff0044,(a6)+
move.l #$ffff0046,(a6)+
;offsets to end of buffers for blitter DESCing
move.l d0,d6 ;len of chscr
move.l d6,d5
lsr.l #1,d5 ;len of buf2
move.l d6,d4
lsr.l #2,d4 ;len of 1 plane = 320*128/8, ok.
*** Pass 1, planes 7654
lea (a0),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea 2(a0),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
move.l a2,(a6)+
move.w #$0054,-2(a6) ;D
move.w a2,(a6)+
move.w #$0056,(a6)+
move.l #$4de40040,(a6)+
move.l #$00000042,(a6)+
move.l #$0f0f0070,(a6)+ ;cdat
move.l #$00020064,(a6)+
move.l #$00020062,(a6)+ ;a/b mod
move.l #$00000066,(a6)+ ;d mod
move.w d4,(a6)+ ;d4: nr_pix/4 (words!)
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
*** Pass 2, planes 76
lea (a2),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea 2(a2),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea (a1),a3
add.w d1,a3
add.w d1,a3
add.w d1,a3 ;4th "doubleplane"
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$2de40040,(a6)+
move.l #$00000042,(a6)+
move.l #$33330070,(a6)+ ;cdat
move.l #$00020064,(a6)+
move.l #$00020062,(a6)+ ;a/b mod
move.l #$00000066,(a6)+ ;d mod
move.w d4,d0
lsr.w #1,d0
move.w d0,(a6)+ ;d4: nr_pix/8 (words!)
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
*** Pass 2, planes 54
lea -2(a2,d5.l),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea -4(a2,d5.l),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea -2(a1,d4.l),a3
add.w d1,a3
add.w d1,a3 ;3rd "doubleplane"
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$2de40040,(a6)+
move.l #$00020042,(a6)+ ;DESC
move.l #$cccc0070,(a6)+ ;cdat
move.l #$00020064,(a6)+
move.l #$00020062,(a6)+ ;a/b mod
move.l #$00000066,(a6)+ ;d mod
move.w d4,d0
lsr.w #1,d0
move.w d0,(a6)+ ;d4: nr_pix/8 (words!)
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
*** Pass 1, planes 3210
lea -2(a0,d6.l),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea -4(a0,d6.l),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea -2(a2,d5.l),a3
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$4de40040,(a6)+
move.l #$00020042,(a6)+
move.l #$f0f00070,(a6)+ ;cdat
move.l #$00020064,(a6)+
move.l #$00020062,(a6)+ ;a/b mod
move.l #$00000066,(a6)+ ;d mod
move.w d4,(a6)+ ;d4: nr_pix/4 (words!)
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
*** Pass 2, planes 32
lea (a2),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea 2(a2),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea (a1),a3
add.w d1,a3 ;2nd "doubleplane"
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$2de40040,(a6)+
move.l #$00000042,(a6)+
move.l #$33330070,(a6)+ ;cdat
move.l #$00020064,(a6)+
move.l #$00020062,(a6)+ ;a/b mod
move.l #$00000066,(a6)+ ;d mod
move.w d4,d0
lsr.w #1,d0
move.w d0,(a6)+ ;d4: nr_pix/8 (words!)
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
*** Pass 2, planes 10
lea -2(a2,d5.l),a3
move.l a3,(a6)+
move.w #$004c,-2(a6) ;B
move.w a3,(a6)+
move.w #$004e,(a6)+
lea -4(a2,d5.l),a3
move.l a3,(a6)+
move.w #$0050,-2(a6) ;A
move.w a3,(a6)+
move.w #$0052,(a6)+
lea -2(a1,d4.l),a3
;1st "doubleplane"
move.l a3,(a6)+
move.w #$0054,-2(a6) ;D
move.w a3,(a6)+
move.w #$0056,(a6)+
move.l #$2de40040,(a6)+
move.l #$00020042,(a6)+ ;DESC
move.l #$cccc0070,(a6)+ ;cdat
move.l #$00020064,(a6)+
move.l #$00020062,(a6)+ ;a/b mod
move.l #$00000066,(a6)+ ;d mod
move.w d4,d0
lsr.w #1,d0
move.w d0,(a6)+ ;d4: nr_pix/8 (words!)
move.w #$5C,(a6)+ ;SIZV
move.l #$0001005E,(a6)+ ;SIZH+start
*** end of initblit
move.l #0,(a6)+
move.w #1,bltbsy ;!!!
waitblt
move.w #$8040,$dff09c ;activate blit intreq
rts
; =============================================================================
;
; M U S I C P L A Y E R
;
; =============================================================================
;**************************************************
;* ----- Protracker V2.3A Playroutine ----- *
;**************************************************
DMAWait = 200 ; Set this as low as possible without losing low notes.
; CIA Version 1:
; Call SetCIAInt to install the interrupt server. Then call mt_init
; to initialize the song. Playback starts when the mt_enable flag
; is set to a nonzero value. To end the song and turn off all voices,
; call mt_end. At last, call ResetCIAInt to remove the interrupt.
; This playroutine is not very fast, optimized or well commented,
; but all the new commands in PT2.3 should work.
; If it's not good enough, you'll have to change it yourself.
; We'll try to write a faster routine soon...
; Changes from V1.0C playroutine:
; - Vibrato depth changed to be compatible with Noisetracker 2.0.
; You'll have to double all vib. depths on old PT modules.
; - Funk Repeat changed to Invert Loop.
; - Period set back earlier when stopping an effect.
;---- CIA Interrupt ----
AddICRVector = -6
RemICRVector = -12
LVOOpenResource = -498
LVOOpenLibrary = -552
LVOCloseLibrary = -414
LVODelay = -198
ciatalo = $400
ciatahi = $500
ciatblo = $600
ciatbhi = $700
ciacra = $E00
ciacrb = $F00
SetCIAInt
MOVEQ #2,D6
LEA $BFD000,A5
MOVE.B #'b',CIAAname+3
SetCIALoop
MOVEQ #0,D0
LEA CIAAname(PC),A1
MOVE.L 4.W,A6
JSR LVOOpenResource(A6)
MOVE.L D0,CIAAbase
BEQ.W mt_Return
LEA GfxName(PC),A1
MOVEQ #0,D0
JSR LVOOpenLibrary(A6)
TST.L D0
BEQ.W ResetCIAInt
MOVE.L D0,A1
MOVE.W 206(A1),D0 ; DisplayFlags
BTST #2,D0 ; PAL?
BEQ.S WasNTSC
MOVE.L #1773447,D7 ; PAL
BRA.S sciask
WasNTSC MOVE.L #1789773,D7 ; NTSC
sciask MOVE.L D7,TimerValue
DIVU #125,D7 ; Default to normal 50 Hz timer
JSR LVOCloseLibrary(A6)
MOVE.L CIAAbase(PC),A6
CMP.W #2,D6
BEQ.S TryTimerA
TryTimerB
LEA MusicIntServer(PC),A1
MOVEQ #1,D0 ; Bit 1: Timer B
JSR AddICRVector(A6)
MOVE.L #1,TimerFlag
TST.L D0
BNE.S CIAError
MOVE.L A5,CIAAaddr
MOVE.B D7,ciatblo(A5)
LSR.W #8,D7
MOVE.B D7,ciatbhi(A5)
BSET #0,ciacrb(A5)
RTS
TryTimerA
LEA MusicIntServer(PC),A1
MOVEQ #0,D0 ; Bit 0: Timer A
JSR AddICRVector(A6)
CLR.L TimerFlag
TST.L D0
BNE.S CIAError
MOVE.L A5,CIAAaddr
MOVE.B D7,ciatalo(A5)
LSR.W #8,D7
MOVE.B D7,ciatahi(A5)
BSET #0,ciacra(A5)
RTS
CIAError
MOVE.B #'a',CIAAname+3
LEA $BFE001,A5
SUBQ.W #1,D6
BNE.W SetCIALoop
CLR.L CIAAbase
RTS
ResetCIAInt
MOVE.L CIAAbase(PC),D0
BEQ.W mt_Return
CLR.L CIAAbase
MOVE.L D0,A6
MOVE.L CIAAaddr(PC),A5
TST.L TimerFlag
BEQ.S ResTimerA
BCLR #0,ciacrb(A5)
MOVEQ #1,D0
BRA.S RemInt
ResTimerA
BCLR #0,ciacra(A5)
MOVEQ #0,D0
RemInt LEA MusicIntServer(PC),A1
MOVEQ #0,d0
JSR RemICRVector(A6)
RTS
;---- Tempo ----
SetTempo
MOVE.L CIAAbase(PC),D2
BEQ.W mt_Return
CMP.W #32,D0
BHS.S setemsk
MOVEQ #32,D0
setemsk MOVE.W D0,RealTempo
MOVE.L TimerValue(PC),D2
DIVU D0,D2
MOVE.L CIAAaddr(PC),A4
MOVE.L TimerFlag(PC),D0
BEQ.S SetTemA
MOVE.B D2,ciatblo(A4)
LSR.W #8,D2
MOVE.B D2,ciatbhi(A4)
RTS
SetTemA MOVE.B D2,ciatalo(A4)
LSR.W #8,D2
MOVE.B D2,ciatahi(A4)
RTS
RealTempo dc.w 125
CIAAaddr dc.l 0
CIAAname dc.b "ciaa.resource",0
CIAAbase dc.l 0
TimerFlag dc.l 0
TimerValue dc.l 0
GfxName dc.b "graphics.library",0,0
MusicIntServer
dc.l 0,0
dc.b 2,5 ; type, priority
dc.l musintname
dc.l 0,mt_music
musintname dc.b "Protracker MusicInt",0
;---- Playroutine ----
n_note EQU 0 ; W
n_cmd EQU 2 ; W
n_cmdlo EQU 3 ; B
n_start EQU 4 ; L
n_length EQU 8 ; W
n_loopstart EQU 10 ; L
n_replen EQU 14 ; W
n_period EQU 16 ; W
n_finetune EQU 18 ; B
n_volume EQU 19 ; B
n_dmabit EQU 20 ; W
n_toneportdirec EQU 22 ; B
n_toneportspeed EQU 23 ; B
n_wantedperiod EQU 24 ; W
n_vibratocmd EQU 26 ; B
n_vibratopos EQU 27 ; B
n_tremolocmd EQU 28 ; B
n_tremolopos EQU 29 ; B
n_wavecontrol EQU 30 ; B
n_glissfunk EQU 31 ; B
n_sampleoffset EQU 32 ; B
n_pattpos EQU 33 ; B
n_loopcount EQU 34 ; B
n_funkoffset EQU 35 ; B
n_wavestart EQU 36 ; L
n_reallength EQU 40 ; W
ALIGNLONG
mt_data dc.l 0
mt_init
move.l mt_data,a0 ; Altered by me...allows for multiple
MOVE.L A0,mt_SongDataPtr ; modules in one source.
MOVE.L A0,A1
LEA 952(A1),A1
MOVEQ #127,D0
MOVEQ #0,D1
mtloop MOVE.L D1,D2
SUBQ.W #1,D0
mtloop2 MOVE.B (A1)+,D1
CMP.B D2,D1
BGT.S mtloop
DBRA D0,mtloop2
ADDQ.B #1,D2
LEA mt_SampleStarts(PC),A1
ASL.L #8,D2
ASL.L #2,D2
ADD.L #1084,D2
ADD.L A0,D2
MOVE.L D2,A2
MOVEQ #30,D0
mtloop3 CLR.L (A2)
MOVE.L A2,(A1)+
MOVEQ #0,D1
MOVE.W 42(A0),D1
ASL.L #1,D1
ADD.L D1,A2
ADD.L #30,A0
DBRA D0,mtloop3
OR.B #2,$BFE001
MOVE.B #6,mt_speed
CLR.B mt_counter
CLR.B mt_SongPos
CLR.W mt_PatternPos
mt_end SF mt_Enable
LEA $DFF000,A0
CLR.W $A8(A0)
CLR.W $B8(A0)
CLR.W $C8(A0)
CLR.W $D8(A0)
MOVE.W #$F,$DFF096
RTS
ALIGNLONG
mt_music
MOVEM.L D0-D4/A0-A6,-(SP)
TST.B mt_Enable
BEQ.W mt_exit
ADDQ.B #1,mt_counter
MOVE.B mt_counter(PC),D0
CMP.B mt_speed(PC),D0
BLO.S mt_NoNewNote
CLR.B mt_counter
TST.B mt_PattDelTime2
BEQ.S mt_GetNewNote
BSR.S mt_NoNewAllChannels
BRA.W mt_dskip
mt_NoNewNote
BSR.S mt_NoNewAllChannels
BRA.W mt_NoNewPosYet
mt_NoNewAllChannels
LEA $DFF0A0,A5
LEA mt_chan1temp(PC),A6
BSR.W mt_CheckEfx
LEA $DFF0B0,A5
LEA mt_chan2temp(PC),A6
BSR.W mt_CheckEfx
LEA $DFF0C0,A5
LEA mt_chan3temp(PC),A6
BSR.W mt_CheckEfx
LEA $DFF0D0,A5
LEA mt_chan4temp(PC),A6
BRA.W mt_CheckEfx
mt_GetNewNote
MOVE.L mt_SongDataPtr(PC),A0
LEA 12(A0),A3
LEA 952(A0),A2 ;pattpo
LEA 1084(A0),A0 ;patterndata
MOVEQ #0,D0
MOVEQ #0,D1
MOVE.B mt_SongPos(PC),D0
MOVE.B (A2,D0.W),D1
ASL.L #8,D1
ASL.L #2,D1
ADD.W mt_PatternPos(PC),D1
CLR.W mt_DMACONtemp
LEA $DFF0A0,A5
LEA mt_chan1temp(PC),A6
BSR.S mt_PlayVoice
LEA $DFF0B0,A5
LEA mt_chan2temp(PC),A6
BSR.S mt_PlayVoice
LEA $DFF0C0,A5
LEA mt_chan3temp(PC),A6
BSR.S mt_PlayVoice
LEA $DFF0D0,A5
LEA mt_chan4temp(PC),A6
BSR.S mt_PlayVoice
BRA.W mt_SetDMA
mt_PlayVoice
TST.L (A6)
BNE.S mt_plvskip
BSR.W mt_PerNop
mt_plvskip
MOVE.L (A0,D1.L),(A6)
ADDQ.L #4,D1
MOVEQ #0,D2
MOVE.B n_cmd(A6),D2
AND.B #$F0,D2
LSR.B #4,D2
MOVE.B (A6),D0
AND.B #$F0,D0
OR.B D0,D2
TST.B D2
BEQ.W mt_SetRegs
MOVEQ #0,D3
LEA mt_SampleStarts(PC),A1
MOVE D2,D4
SUBQ.L #1,D2
ASL.L #2,D2
MULU #30,D4
MOVE.L (A1,D2.L),n_start(A6)
MOVE.W (A3,D4.L),n_length(A6)
MOVE.W (A3,D4.L),n_reallength(A6)
MOVE.B 2(A3,D4.L),n_finetune(A6)
MOVE.B 3(A3,D4.L),n_volume(A6)
MOVE.W 4(A3,D4.L),D3 ; Get repeat
TST.W D3
BEQ.S mt_NoLoop
MOVE.L n_start(A6),D2 ; Get start
ASL.W #1,D3
ADD.L D3,D2 ; Add repeat
MOVE.L D2,n_loopstart(A6)
MOVE.L D2,n_wavestart(A6)
MOVE.W 4(A3,D4.L),D0 ; Get repeat
ADD.W 6(A3,D4.L),D0 ; Add replen
MOVE.W D0,n_length(A6)
MOVE.W 6(A3,D4.L),n_replen(A6) ; Save replen
MOVEQ #0,D0
MOVE.B n_volume(A6),D0
MOVE.W D0,8(A5) ; Set volume
BRA.S mt_SetRegs
mt_NoLoop
MOVE.L n_start(A6),D2
ADD.L D3,D2
MOVE.L D2,n_loopstart(A6)
MOVE.L D2,n_wavestart(A6)
MOVE.W 6(A3,D4.L),n_replen(A6) ; Save replen
MOVEQ #0,D0
MOVE.B n_volume(A6),D0
MOVE.W D0,8(A5) ; Set volume
mt_SetRegs
MOVE.W (A6),D0
AND.W #$0FFF,D0
BEQ.W mt_CheckMoreEfx ; If no note
MOVE.W 2(A6),D0
AND.W #$0FF0,D0
CMP.W #$0E50,D0
BEQ.S mt_DoSetFineTune
MOVE.B 2(A6),D0
AND.B #$0F,D0
CMP.B #3,D0 ; TonePortamento
BEQ.S mt_ChkTonePorta
CMP.B #5,D0
BEQ.S mt_ChkTonePorta
CMP.B #9,D0 ; Sample Offset
BNE.S mt_SetPeriod
BSR.W mt_CheckMoreEfx
BRA.S mt_SetPeriod
mt_DoSetFineTune
BSR.W mt_SetFineTune
BRA.S mt_SetPeriod
mt_ChkTonePorta
BSR.W mt_SetTonePorta
BRA.W mt_CheckMoreEfx
mt_SetPeriod
MOVEM.L D0-D1/A0-A1,-(SP)
MOVE.W (A6),D1
AND.W #$0FFF,D1
LEA mt_PeriodTable(PC),A1
MOVEQ #0,D0
MOVEQ #36,D2
mt_ftuloop
CMP.W (A1,D0.W),D1
BHS.S mt_ftufound
ADDQ.L #2,D0
DBRA D2,mt_ftuloop
mt_ftufound
MOVEQ #0,D1
MOVE.B n_finetune(A6),D1
MULU #36*2,D1
ADD.L D1,A1
MOVE.W (A1,D0.W),n_period(A6)
MOVEM.L (SP)+,D0-D1/A0-A1
MOVE.W 2(A6),D0
AND.W #$0FF0,D0
CMP.W #$0ED0,D0 ; Notedelay
BEQ.W mt_CheckMoreEfx
MOVE.W n_dmabit(A6),$DFF096
BTST #2,n_wavecontrol(A6)
BNE.S mt_vibnoc
CLR.B n_vibratopos(A6)
mt_vibnoc
BTST #6,n_wavecontrol(A6)
BNE.S mt_trenoc
CLR.B n_tremolopos(A6)
mt_trenoc
MOVE.L n_start(A6),(A5) ; Set start
MOVE.W n_length(A6),4(A5) ; Set length
MOVE.W n_period(A6),D0
MOVE.W D0,6(A5) ; Set period
MOVE.W n_dmabit(A6),D0
OR.W D0,mt_DMACONtemp
BRA.W mt_CheckMoreEfx
mt_SetDMA
MOVE.W #300,D0
mt_WaitDMA
DBRA D0,mt_WaitDMA
MOVE.W mt_DMACONtemp(PC),D0
OR.W #$8000,D0
MOVE.W D0,$DFF096
MOVE.W #300,D0
mt_WaitDMA2
DBRA D0,mt_WaitDMA2
LEA $DFF000,A5
LEA mt_chan4temp(PC),A6
MOVE.L n_loopstart(A6),$D0(A5)
MOVE.W n_replen(A6),$D4(A5)
LEA mt_chan3temp(PC),A6
MOVE.L n_loopstart(A6),$C0(A5)
MOVE.W n_replen(A6),$C4(A5)
LEA mt_chan2temp(PC),A6
MOVE.L n_loopstart(A6),$B0(A5)
MOVE.W n_replen(A6),$B4(A5)
LEA mt_chan1temp(PC),A6
MOVE.L n_loopstart(A6),$A0(A5)
MOVE.W n_replen(A6),$A4(A5)
mt_dskip
ADD.W #16,mt_PatternPos
MOVE.B mt_PattDelTime,D0
BEQ.S mt_dskc
MOVE.B D0,mt_PattDelTime2
CLR.B mt_PattDelTime
mt_dskc TST.B mt_PattDelTime2
BEQ.S mt_dska
SUBQ.B #1,mt_PattDelTime2
BEQ.S mt_dska
SUB.W #16,mt_PatternPos
mt_dska TST.B mt_PBreakFlag
BEQ.S mt_nnpysk
SF mt_PBreakFlag
MOVEQ #0,D0
MOVE.B mt_PBreakPos(PC),D0
CLR.B mt_PBreakPos
LSL.W #4,D0
MOVE.W D0,mt_PatternPos
mt_nnpysk
CMP.W #1024,mt_PatternPos
BLO.S mt_NoNewPosYet
mt_NextPosition
MOVEQ #0,D0
MOVE.B mt_PBreakPos(PC),D0
LSL.W #4,D0
MOVE.W D0,mt_PatternPos
CLR.B mt_PBreakPos
CLR.B mt_PosJumpFlag
ADDQ.B #1,mt_SongPos
AND.B #$7F,mt_SongPos
MOVE.B mt_SongPos(PC),D1
MOVE.L mt_SongDataPtr(PC),A0
CMP.B 950(A0),D1
BLO.S mt_NoNewPosYet
CLR.B mt_SongPos
mt_NoNewPosYet
TST.B mt_PosJumpFlag
BNE.S mt_NextPosition
mt_exit MOVEM.L (SP)+,D0-D4/A0-A6
RTS
mt_CheckEfx
BSR.W mt_UpdateFunk
MOVE.W n_cmd(A6),D0
AND.W #$0FFF,D0
BEQ.S mt_PerNop
MOVE.B n_cmd(A6),D0
AND.B #$0F,D0
BEQ.S mt_Arpeggio
CMP.B #1,D0
BEQ.W mt_PortaUp
CMP.B #2,D0
BEQ.W mt_PortaDown
CMP.B #3,D0
BEQ.W mt_TonePortamento
CMP.B #4,D0
BEQ.W mt_Vibrato
CMP.B #5,D0
BEQ.W mt_TonePlusVolSlide
CMP.B #6,D0
BEQ.W mt_VibratoPlusVolSlide
CMP.B #$E,D0
BEQ.W mt_E_Commands
SetBack MOVE.W n_period(A6),6(A5)
CMP.B #7,D0
BEQ.W mt_Tremolo
CMP.B #$A,D0
BEQ.W mt_VolumeSlide
mt_Return
RTS
mt_PerNop
MOVE.W n_period(A6),6(A5)
RTS
mt_Arpeggio
MOVEQ #0,D0
MOVE.B mt_counter(PC),D0
DIVS #3,D0
SWAP D0
CMP.W #0,D0
BEQ.S mt_Arpeggio2
CMP.W #2,D0
BEQ.S mt_Arpeggio1
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
LSR.B #4,D0
BRA.S mt_Arpeggio3
mt_Arpeggio1
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #15,D0
BRA.S mt_Arpeggio3
mt_Arpeggio2
MOVE.W n_period(A6),D2
BRA.S mt_Arpeggio4
mt_Arpeggio3
ASL.W #1,D0
MOVEQ #0,D1
MOVE.B n_finetune(A6),D1
MULU #36*2,D1
LEA mt_PeriodTable(PC),A0
ADD.L D1,A0
MOVEQ #0,D1
MOVE.W n_period(A6),D1
MOVEQ #36,D3
mt_arploop
MOVE.W (A0,D0.W),D2
CMP.W (A0),D1
BHS.S mt_Arpeggio4
ADDQ.L #2,A0
DBRA D3,mt_arploop
RTS
mt_Arpeggio4
MOVE.W D2,6(A5)
RTS
mt_FinePortaUp
TST.B mt_counter
BNE.S mt_Return
MOVE.B #$0F,mt_LowMask
mt_PortaUp
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B mt_LowMask(PC),D0
MOVE.B #$FF,mt_LowMask
SUB.W D0,n_period(A6)
MOVE.W n_period(A6),D0
AND.W #$0FFF,D0
CMP.W #113,D0
BPL.S mt_PortaUskip
AND.W #$F000,n_period(A6)
OR.W #113,n_period(A6)
mt_PortaUskip
MOVE.W n_period(A6),D0
AND.W #$0FFF,D0
MOVE.W D0,6(A5)
RTS
mt_FinePortaDown
TST.B mt_counter
BNE.W mt_Return
MOVE.B #$0F,mt_LowMask
mt_PortaDown
CLR.W D0
MOVE.B n_cmdlo(A6),D0
AND.B mt_LowMask(PC),D0
MOVE.B #$FF,mt_LowMask
ADD.W D0,n_period(A6)
MOVE.W n_period(A6),D0
AND.W #$0FFF,D0
CMP.W #856,D0
BMI.S mt_PortaDskip
AND.W #$F000,n_period(A6)
OR.W #856,n_period(A6)
mt_PortaDskip
MOVE.W n_period(A6),D0
AND.W #$0FFF,D0
MOVE.W D0,6(A5)
RTS
mt_SetTonePorta
MOVE.L A0,-(SP)
MOVE.W (A6),D2
AND.W #$0FFF,D2
MOVEQ #0,D0
MOVE.B n_finetune(A6),D0
MULU #36*2,D0 ;37?
LEA mt_PeriodTable(PC),A0
ADD.L D0,A0
MOVEQ #0,D0
mt_StpLoop
CMP.W (A0,D0.W),D2
BHS.S mt_StpFound
ADDQ.W #2,D0
CMP.W #36*2,D0 ;37?
BLO.S mt_StpLoop
MOVEQ #35*2,D0
mt_StpFound
MOVE.B n_finetune(A6),D2
AND.B #8,D2
BEQ.S mt_StpGoss
TST.W D0
BEQ.S mt_StpGoss
SUBQ.W #2,D0
mt_StpGoss
MOVE.W (A0,D0.W),D2
MOVE.L (SP)+,A0
MOVE.W D2,n_wantedperiod(A6)
MOVE.W n_period(A6),D0
CLR.B n_toneportdirec(A6)
CMP.W D0,D2
BEQ.S mt_ClearTonePorta
BGE.W mt_Return
MOVE.B #1,n_toneportdirec(A6)
RTS
mt_ClearTonePorta
CLR.W n_wantedperiod(A6)
RTS
mt_TonePortamento
MOVE.B n_cmdlo(A6),D0
BEQ.S mt_TonePortNoChange
MOVE.B D0,n_toneportspeed(A6)
CLR.B n_cmdlo(A6)
mt_TonePortNoChange
TST.W n_wantedperiod(A6)
BEQ.W mt_Return
MOVEQ #0,D0
MOVE.B n_toneportspeed(A6),D0
TST.B n_toneportdirec(A6)
BNE.S mt_TonePortaUp
mt_TonePortaDown
ADD.W D0,n_period(A6)
MOVE.W n_wantedperiod(A6),D0
CMP.W n_period(A6),D0
BGT.S mt_TonePortaSetPer
MOVE.W n_wantedperiod(A6),n_period(A6)
CLR.W n_wantedperiod(A6)
BRA.S mt_TonePortaSetPer
mt_TonePortaUp
SUB.W D0,n_period(A6)
MOVE.W n_wantedperiod(A6),D0
CMP.W n_period(A6),D0
BLT.S mt_TonePortaSetPer
MOVE.W n_wantedperiod(A6),n_period(A6)
CLR.W n_wantedperiod(A6)
mt_TonePortaSetPer
MOVE.W n_period(A6),D2
MOVE.B n_glissfunk(A6),D0
AND.B #$0F,D0
BEQ.S mt_GlissSkip
MOVEQ #0,D0
MOVE.B n_finetune(A6),D0
MULU #36*2,D0
LEA mt_PeriodTable(PC),A0
ADD.L D0,A0
MOVEQ #0,D0
mt_GlissLoop
CMP.W (A0,D0.W),D2
BHS.S mt_GlissFound
ADDQ.W #2,D0
CMP.W #36*2,D0
BLO.S mt_GlissLoop
MOVEQ #35*2,D0
mt_GlissFound
MOVE.W (A0,D0.W),D2
mt_GlissSkip
MOVE.W D2,6(A5) ; Set period
RTS
mt_Vibrato
MOVE.B n_cmdlo(A6),D0
BEQ.S mt_Vibrato2
MOVE.B n_vibratocmd(A6),D2
AND.B #$0F,D0
BEQ.S mt_vibskip
AND.B #$F0,D2
OR.B D0,D2
mt_vibskip
MOVE.B n_cmdlo(A6),D0
AND.B #$F0,D0
BEQ.S mt_vibskip2
AND.B #$0F,D2
OR.B D0,D2
mt_vibskip2
MOVE.B D2,n_vibratocmd(A6)
mt_Vibrato2
MOVE.B n_vibratopos(A6),D0
LEA mt_VibratoTable(PC),A4
LSR.W #2,D0
AND.W #$001F,D0
MOVEQ #0,D2
MOVE.B n_wavecontrol(A6),D2
AND.B #$03,D2
BEQ.S mt_vib_sine
LSL.B #3,D0
CMP.B #1,D2
BEQ.S mt_vib_rampdown
MOVE.B #255,D2
BRA.S mt_vib_set
mt_vib_rampdown
TST.B n_vibratopos(A6)
BPL.S mt_vib_rampdown2
MOVE.B #255,D2
SUB.B D0,D2
BRA.S mt_vib_set
mt_vib_rampdown2
MOVE.B D0,D2
BRA.S mt_vib_set
mt_vib_sine
MOVE.B (A4,D0.W),D2
mt_vib_set
MOVE.B n_vibratocmd(A6),D0
AND.W #15,D0
MULU D0,D2
LSR.W #7,D2
MOVE.W n_period(A6),D0
TST.B n_vibratopos(A6)
BMI.S mt_VibratoNeg
ADD.W D2,D0
BRA.S mt_Vibrato3
mt_VibratoNeg
SUB.W D2,D0
mt_Vibrato3
MOVE.W D0,6(A5)
MOVE.B n_vibratocmd(A6),D0
LSR.W #2,D0
AND.W #$003C,D0
ADD.B D0,n_vibratopos(A6)
RTS
mt_TonePlusVolSlide
BSR.W mt_TonePortNoChange
BRA.W mt_VolumeSlide
mt_VibratoPlusVolSlide
BSR.S mt_Vibrato2
BRA.W mt_VolumeSlide
mt_Tremolo
MOVE.B n_cmdlo(A6),D0
BEQ.S mt_Tremolo2
MOVE.B n_tremolocmd(A6),D2
AND.B #$0F,D0
BEQ.S mt_treskip
AND.B #$F0,D2
OR.B D0,D2
mt_treskip
MOVE.B n_cmdlo(A6),D0
AND.B #$F0,D0
BEQ.S mt_treskip2
AND.B #$0F,D2
OR.B D0,D2
mt_treskip2
MOVE.B D2,n_tremolocmd(A6)
mt_Tremolo2
MOVE.B n_tremolopos(A6),D0
LEA mt_VibratoTable(PC),A4
LSR.W #2,D0
AND.W #$001F,D0
MOVEQ #0,D2
MOVE.B n_wavecontrol(A6),D2
LSR.B #4,D2
AND.B #$03,D2
BEQ.S mt_tre_sine
LSL.B #3,D0
CMP.B #1,D2
BEQ.S mt_tre_rampdown
MOVE.B #255,D2
BRA.S mt_tre_set
mt_tre_rampdown
TST.B n_vibratopos(A6)
BPL.S mt_tre_rampdown2
MOVE.B #255,D2
SUB.B D0,D2
BRA.S mt_tre_set
mt_tre_rampdown2
MOVE.B D0,D2
BRA.S mt_tre_set
mt_tre_sine
MOVE.B (A4,D0.W),D2
mt_tre_set
MOVE.B n_tremolocmd(A6),D0
AND.W #15,D0
MULU D0,D2
LSR.W #6,D2
MOVEQ #0,D0
MOVE.B n_volume(A6),D0
TST.B n_tremolopos(A6)
BMI.S mt_TremoloNeg
ADD.W D2,D0
BRA.S mt_Tremolo3
mt_TremoloNeg
SUB.W D2,D0
mt_Tremolo3
BPL.S mt_TremoloSkip
CLR.W D0
mt_TremoloSkip
CMP.W #$40,D0
BLS.S mt_TremoloOk
MOVE.W #$40,D0
mt_TremoloOk
MOVE.W D0,8(A5)
MOVE.B n_tremolocmd(A6),D0
LSR.W #2,D0
AND.W #$003C,D0
ADD.B D0,n_tremolopos(A6)
RTS
mt_SampleOffset
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
BEQ.S mt_sononew
MOVE.B D0,n_sampleoffset(A6)
mt_sononew
MOVE.B n_sampleoffset(A6),D0
LSL.W #7,D0
CMP.W n_length(A6),D0
BGE.S mt_sofskip
SUB.W D0,n_length(A6)
LSL.W #1,D0
ADD.L D0,n_start(A6)
RTS
mt_sofskip
MOVE.W #$0001,n_length(A6)
RTS
mt_VolumeSlide
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
LSR.B #4,D0
TST.B D0
BEQ.S mt_VolSlideDown
mt_VolSlideUp
ADD.B D0,n_volume(A6)
CMP.B #$40,n_volume(A6)
BMI.S mt_vsuskip
MOVE.B #$40,n_volume(A6)
mt_vsuskip
MOVE.B n_volume(A6),D0
MOVE.W D0,8(A5)
RTS
mt_VolSlideDown
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
mt_VolSlideDown2
SUB.B D0,n_volume(A6)
BPL.S mt_vsdskip
CLR.B n_volume(A6)
mt_vsdskip
MOVE.B n_volume(A6),D0
MOVE.W D0,8(A5)
RTS
mt_PositionJump
MOVE.B n_cmdlo(A6),D0
SUBQ.B #1,D0
MOVE.B D0,mt_SongPos
mt_pj2 CLR.B mt_PBreakPos
ST mt_PosJumpFlag
RTS
mt_VolumeChange
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
CMP.B #$40,D0
BLS.S mt_VolumeOk
MOVEQ #$40,D0
mt_VolumeOk
MOVE.B D0,n_volume(A6)
MOVE.W D0,8(A5)
RTS
mt_PatternBreak
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
MOVE.L D0,D2
LSR.B #4,D0
MULU #10,D0
AND.B #$0F,D2
ADD.B D2,D0
CMP.B #63,D0
BHI.S mt_pj2
MOVE.B D0,mt_PBreakPos
ST mt_PosJumpFlag
RTS
mt_SetSpeed
MOVEQ #0,D0
MOVE.B 3(A6),D0
BEQ.W mt_end
CMP.B #32,D0
BHS.W SetTempo
CLR.B mt_counter
MOVE.B D0,mt_speed
RTS
mt_CheckMoreEfx
BSR.W mt_UpdateFunk
MOVE.B 2(A6),D0
AND.B #$0F,D0
CMP.B #$9,D0
BEQ.W mt_SampleOffset
CMP.B #$B,D0
BEQ.W mt_PositionJump
CMP.B #$D,D0
BEQ.S mt_PatternBreak
CMP.B #$E,D0
BEQ.S mt_E_Commands
CMP.B #$F,D0
BEQ.S mt_SetSpeed
CMP.B #$C,D0
BEQ.W mt_VolumeChange
BRA.W mt_PerNop
mt_E_Commands
MOVE.B n_cmdlo(A6),D0
AND.B #$F0,D0
LSR.B #4,D0
BEQ.S mt_FilterOnOff
CMP.B #1,D0
BEQ.W mt_FinePortaUp
CMP.B #2,D0
BEQ.W mt_FinePortaDown
CMP.B #3,D0
BEQ.S mt_SetGlissControl
CMP.B #4,D0
BEQ.W mt_SetVibratoControl
CMP.B #5,D0
BEQ.W mt_SetFineTune
CMP.B #6,D0
BEQ.W mt_JumpLoop
CMP.B #7,D0
BEQ.W mt_SetTremoloControl
CMP.B #9,D0
BEQ.W mt_RetrigNote
CMP.B #$A,D0
BEQ.W mt_VolumeFineUp
CMP.B #$B,D0
BEQ.W mt_VolumeFineDown
CMP.B #$C,D0
BEQ.W mt_NoteCut
CMP.B #$D,D0
BEQ.W mt_NoteDelay
CMP.B #$E,D0
BEQ.W mt_PatternDelay
CMP.B #$F,D0
BEQ.W mt_FunkIt
RTS
mt_FilterOnOff
MOVE.B n_cmdlo(A6),D0
AND.B #1,D0
ASL.B #1,D0
AND.B #$FD,$BFE001
OR.B D0,$BFE001
RTS
mt_SetGlissControl
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
AND.B #$F0,n_glissfunk(A6)
OR.B D0,n_glissfunk(A6)
RTS
mt_SetVibratoControl
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
AND.B #$F0,n_wavecontrol(A6)
OR.B D0,n_wavecontrol(A6)
RTS
mt_SetFineTune
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
MOVE.B D0,n_finetune(A6)
RTS
mt_JumpLoop
TST.B mt_counter
BNE.W mt_Return
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
BEQ.S mt_SetLoop
TST.B n_loopcount(A6)
BEQ.S mt_jumpcnt
SUBQ.B #1,n_loopcount(A6)
BEQ.W mt_Return
mt_jmploop MOVE.B n_pattpos(A6),mt_PBreakPos
ST mt_PBreakFlag
RTS
mt_jumpcnt
MOVE.B D0,n_loopcount(A6)
BRA.S mt_jmploop
mt_SetLoop
MOVE.W mt_PatternPos(PC),D0
LSR.W #4,D0
MOVE.B D0,n_pattpos(A6)
RTS
mt_SetTremoloControl
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
LSL.B #4,D0
AND.B #$0F,n_wavecontrol(A6)
OR.B D0,n_wavecontrol(A6)
RTS
mt_RetrigNote
MOVE.L D1,-(SP)
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
BEQ.S mt_rtnend
MOVEQ #0,D1
MOVE.B mt_counter(PC),D1
BNE.S mt_rtnskp
MOVE.W (A6),D1
AND.W #$0FFF,D1
BNE.S mt_rtnend
MOVEQ #0,D1
MOVE.B mt_counter(PC),D1
mt_rtnskp
DIVU D0,D1
SWAP D1
TST.W D1
BNE.S mt_rtnend
mt_DoRetrig
MOVE.W n_dmabit(A6),$DFF096 ; Channel DMA off
MOVE.L n_start(A6),(A5) ; Set sampledata pointer
MOVE.W n_length(A6),4(A5) ; Set length
MOVE.W #300,D0
mt_rtnloop1
DBRA D0,mt_rtnloop1
MOVE.W n_dmabit(A6),D0
BSET #15,D0
MOVE.W D0,$DFF096
MOVE.W #300,D0
mt_rtnloop2
DBRA D0,mt_rtnloop2
MOVE.L n_loopstart(A6),(A5)
MOVE.L n_replen(A6),4(A5)
mt_rtnend
MOVE.L (SP)+,D1
RTS
mt_VolumeFineUp
TST.B mt_counter
BNE.W mt_Return
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$F,D0
BRA.W mt_VolSlideUp
mt_VolumeFineDown
TST.B mt_counter
BNE.W mt_Return
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
BRA.W mt_VolSlideDown2
mt_NoteCut
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
CMP.B mt_counter(PC),D0
BNE.W mt_Return
CLR.B n_volume(A6)
MOVE.W #0,8(A5)
RTS
mt_NoteDelay
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
CMP.B mt_counter,D0
BNE.W mt_Return
MOVE.W (A6),D0
BEQ.W mt_Return
MOVE.L D1,-(SP)
BRA.W mt_DoRetrig
mt_PatternDelay
TST.B mt_counter
BNE.W mt_Return
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
TST.B mt_PattDelTime2
BNE.W mt_Return
ADDQ.B #1,D0
MOVE.B D0,mt_PattDelTime
RTS
mt_FunkIt
TST.B mt_counter
BNE.W mt_Return
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
LSL.B #4,D0
AND.B #$0F,n_glissfunk(A6)
OR.B D0,n_glissfunk(A6)
TST.B D0
BEQ.W mt_Return
mt_UpdateFunk
MOVEM.L A0/D1,-(SP)
MOVEQ #0,D0
MOVE.B n_glissfunk(A6),D0
LSR.B #4,D0
BEQ.S mt_funkend
LEA mt_FunkTable(PC),A0
MOVE.B (A0,D0.W),D0
ADD.B D0,n_funkoffset(A6)
BTST #7,n_funkoffset(A6)
BEQ.S mt_funkend
CLR.B n_funkoffset(A6)
MOVE.L n_loopstart(A6),D0
MOVEQ #0,D1
MOVE.W n_replen(A6),D1
ADD.L D1,D0
ADD.L D1,D0
MOVE.L n_wavestart(A6),A0
ADDQ.L #1,A0
CMP.L D0,A0
BLO.S mt_funkok
MOVE.L n_loopstart(A6),A0
mt_funkok
MOVE.L A0,n_wavestart(A6)
MOVEQ #-1,D0
SUB.B (A0),D0
MOVE.B D0,(A0)
mt_funkend
MOVEM.L (SP)+,A0/D1
RTS
mt_FunkTable dc.b 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128
mt_VibratoTable
dc.b 0, 24, 49, 74, 97,120,141,161
dc.b 180,197,212,224,235,244,250,253
dc.b 255,253,250,244,235,224,212,197
dc.b 180,161,141,120, 97, 74, 49, 24
mt_PeriodTable
; Tuning 0, Normal
dc.w 856,808,762,720,678,640,604,570,538,508,480,453
dc.w 428,404,381,360,339,320,302,285,269,254,240,226
dc.w 214,202,190,180,170,160,151,143,135,127,120,113
; Tuning 1
dc.w 850,802,757,715,674,637,601,567,535,505,477,450
dc.w 425,401,379,357,337,318,300,284,268,253,239,225
dc.w 213,201,189,179,169,159,150,142,134,126,119,113
; Tuning 2
dc.w 844,796,752,709,670,632,597,563,532,502,474,447
dc.w 422,398,376,355,335,316,298,282,266,251,237,224
dc.w 211,199,188,177,167,158,149,141,133,125,118,112
; Tuning 3
dc.w 838,791,746,704,665,628,592,559,528,498,470,444
dc.w 419,395,373,352,332,314,296,280,264,249,235,222
dc.w 209,198,187,176,166,157,148,140,132,125,118,111
; Tuning 4
dc.w 832,785,741,699,660,623,588,555,524,495,467,441
dc.w 416,392,370,350,330,312,294,278,262,247,233,220
dc.w 208,196,185,175,165,156,147,139,131,124,117,110
; Tuning 5
dc.w 826,779,736,694,655,619,584,551,520,491,463,437
dc.w 413,390,368,347,328,309,292,276,260,245,232,219
dc.w 206,195,184,174,164,155,146,138,130,123,116,109
; Tuning 6
dc.w 820,774,730,689,651,614,580,547,516,487,460,434
dc.w 410,387,365,345,325,307,290,274,258,244,230,217
dc.w 205,193,183,172,163,154,145,137,129,122,115,109
; Tuning 7
dc.w 814,768,725,684,646,610,575,543,513,484,457,431
dc.w 407,384,363,342,323,305,288,272,256,242,228,216
dc.w 204,192,181,171,161,152,144,136,128,121,114,108
; Tuning -8
dc.w 907,856,808,762,720,678,640,604,570,538,508,480
dc.w 453,428,404,381,360,339,320,302,285,269,254,240
dc.w 226,214,202,190,180,170,160,151,143,135,127,120
; Tuning -7
dc.w 900,850,802,757,715,675,636,601,567,535,505,477
dc.w 450,425,401,379,357,337,318,300,284,268,253,238
dc.w 225,212,200,189,179,169,159,150,142,134,126,119
; Tuning -6
dc.w 894,844,796,752,709,670,632,597,563,532,502,474
dc.w 447,422,398,376,355,335,316,298,282,266,251,237
dc.w 223,211,199,188,177,167,158,149,141,133,125,118
; Tuning -5
dc.w 887,838,791,746,704,665,628,592,559,528,498,470
dc.w 444,419,395,373,352,332,314,296,280,264,249,235
dc.w 222,209,198,187,176,166,157,148,140,132,125,118
; Tuning -4
dc.w 881,832,785,741,699,660,623,588,555,524,494,467
dc.w 441,416,392,370,350,330,312,294,278,262,247,233
dc.w 220,208,196,185,175,165,156,147,139,131,123,117
; Tuning -3
dc.w 875,826,779,736,694,655,619,584,551,520,491,463
dc.w 437,413,390,368,347,328,309,292,276,260,245,232
dc.w 219,206,195,184,174,164,155,146,138,130,123,116
; Tuning -2
dc.w 868,820,774,730,689,651,614,580,547,516,487,460
dc.w 434,410,387,365,345,325,307,290,274,258,244,230
dc.w 217,205,193,183,172,163,154,145,137,129,122,115
; Tuning -1
dc.w 862,814,768,725,684,646,610,575,543,513,484,457
dc.w 431,407,384,363,342,323,305,288,272,256,242,228
dc.w 216,203,192,181,171,161,152,144,136,128,121,114
mt_chan1temp dc.l 0,0,0,0,0,$00010000,0, 0,0,0,0
mt_chan2temp dc.l 0,0,0,0,0,$00020000,0, 0,0,0,0
mt_chan3temp dc.l 0,0,0,0,0,$00040000,0, 0,0,0,0
mt_chan4temp dc.l 0,0,0,0,0,$00080000,0, 0,0,0,0
mt_SampleStarts dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
mt_SongDataPtr dc.l 0
mt_speed dc.b 6
mt_counter dc.b 0
mt_SongPos dc.b 0
mt_PBreakPos dc.b 0
mt_PosJumpFlag dc.b 0
mt_PBreakFlag dc.b 0
mt_LowMask dc.b 0
mt_PattDelTime dc.b 0
mt_PattDelTime2 dc.b 0
mt_Enable dc.b 0
mt_PatternPos dc.w 0
mt_DMACONtemp dc.w 0
;/* End of File */
; =============================================================================
;
; D A T A
;
; =============================================================================
; *****************************************************************************
; Copperlist header
; *****************************************************************************
ALIGNQUAD
COL32 MACRO
dc.l $01800000,$01820000,$01840000,$01860000,$01880000,$018a0000
dc.l $018c0000,$018e0000,$01900000,$01920000,$01940000,$01960000
dc.l $01980000,$019a0000,$019c0000,$019e0000,$01a00000,$01a20000
dc.l $01a40000,$01a60000,$01a80000,$01aa0000,$01ac0000,$01ae0000
dc.l $01b00000,$01b20000,$01b40000,$01b60000,$01b80000,$01ba0000
dc.l $01bc0000,$01be0000
ENDM
Cop
dc.l $01fc400f ;FMODE Bpl=3, Spr=3, ScanDouble (2x2)
dc.l $00968100 ;DMACON Plane dma on line 0
dc.l $01000211 ;BPLCON0 Lores, 8 planes, ECS on
dc.l $01020000 ;BPLCON1
dc.l $0104003f ;BPLCON2 Sprite priority!
dc.l $01060020 ;BPLCON3 BBlank
dc.l $010c0000 ;BPLCON4 Sprite-colorbank (!)
dc.l $0108ffd8 ;BPL1MOD 2x2: modulo = -40
dc.l $010a0000 ;BPL2MOD
dc.l $008e2881 ;
dc.l $009028c1 ;
dc.l $00920038 ;
dc.l $009400a0 ;
CopBpl ; Bitplane pointers
dc.l $00e00000,$00e20000
dc.l $00e40000,$00e60002
dc.l $00e80000,$00ea0004
dc.l $00ec0000,$00ee0006
dc.l $00f00000,$00f20008
dc.l $00f40000,$00f6000a
dc.l $00f80000,$00fa000c
dc.l $00fc0000,$00fe000e
CopCol ; Colour registers (24 bit HL)
dc.l $01060c60
COL32
dc.l $01060e60
COL32
dc.l $01062c60
COL32
dc.l $01062e60
COL32
dc.l $01064c60
COL32
dc.l $01064e60
COL32
dc.l $01066c60
COL32
dc.l $01066e60
COL32
dc.l $01068c60
COL32
dc.l $01068e60
COL32
dc.l $0106ac60
COL32
dc.l $0106ae60
COL32
dc.l $0106cc60
COL32
dc.l $0106ce60
COL32
dc.l $0106ec60
COL32
dc.l $0106ee60
COL32
CopEnd
; *****************************************************************************
; Variables
; *****************************************************************************
ALIGNLONG
Joy1Left dc.b 0 ; Joystick direction
Joy1Right dc.b 0
Joy1Up dc.b 0
Joy1Down dc.b 0
Joy1Fire dc.b 0
KeyRaw dc.b 0 ; Raw code of last pressed key
KeyState dc.b 0 ; State of last pressed key
ALIGNLONG
RendCh dc.l 0 ; }_ Chunky buffer
DispCh dc.l 0 ; }
RendBL dc.l 0 ; }_ Blitterlist
DispBL dc.l 0 ; }
RendCop dc.l 0 ; }_ Copperlist
DispCop dc.l 0 ; }
Plyr_Z dc.l 0 ; Z-position
Plyr_ZSpd dc.w 0 ; Tunnel scroll speed (in texels)
Plyr_Scroll dc.w 0 ; Tunnel scroll position (in texels)
Plyr_X dc.w 0 ; }_ Center-coordinates of player ship
Plyr_Y dc.w 0 ; }
Plyr_XSpd dc.w 0 ; }_ Speed
Plyr_YSpd dc.w 0 ; }
Plyr_Level dc.w 0 ; Current level number
Plyr_Ships dc.w 0 ; Number of remaining ships
Plyr_Time dc.l 0 ; Time left for this level
Plyr_Frame dc.w 0 ; Animation frame number
Plyr_EngineCnt dc.w 0 ; Engine colour counter
Plyr_EngineOn dc.w 0 ; True is engine is on, false if off
Plyr_Name dcb.b MaxStrLen+1,0 ; Name of player
Plyr_Cheat dc.b 0 ; Cheatmode on / off
ALIGNLONG
Game_Flags dc.l 0 ; Game-loop status flags
Game_FirstWall dc.w 0 ; Number of first visible wall
Game_LastWall dc.w 0 ; Number of last visible wall
Game_WallZ dc.l 0 ; Pointer to Wall_Z array
Game_WallType dc.l 0 ; Pointer to Wall_Type array
Game_LevelPtr dc.l 0 ; Pointer to Level array
Toggle dc.l 0 ; Toggles between 0 and 1
ToggleCnt dc.l 0 ; Time depends on max. ToggleCnt
FlgTimer dc.l 0 ; Gameloop statusflag timer thing
BestTimes dcb.l 9,0 ; Best track times
BestNames dcb.b 9*12,0 ; Names of best racers
RealTimeCnt dc.l 0 ; RealTime counter
RealTime dc.l 0 ; RealTime value
Intro_Timer dc.l 0 ; Intro timer
Intro_Flags dc.l 0 ; Intro status-flags
Intro_WarpIn dc.b 0 ; Intro warp-in is active
Intro_WarpOut dc.b 0 ; Intro warp-out is active
Intro_WarpCount dc.w 0 ; Intro warp-in/out counter
Intro_Level dc.w 0 ; Levelnr for Track Select
; *****************************************************************************
; Level Data
; *****************************************************************************
ALIGNLONG
Level ; Level 1 -----------------------------------------------------
dc.w 34,3 ; NumWalls, Ships
dc.l 1500 ; Time
; Level 2 -----------------------------------------------------
dc.w 34,4
dc.l 1500
; Level 3 -----------------------------------------------------
dc.w 34,2
dc.l 1000
; Level 4 -----------------------------------------------------
dc.w 14,1
dc.l 500
; Level 5 -----------------------------------------------------
dc.w 50,3
dc.l 2000
Wall_Z ; Level 1 -----------------------------------------------------
dc.l 512
dc.l 01*1024,02*1024,03*1024,04*1024
dc.l 05*1024,06*1024,07*1024,08*1024
dc.l 09*1024,10*1024,11*1024,12*1024
dc.l 13*1024,14*1024,15*1024,16*1024
dc.l 17*1024,18*1024,19*1024,20*1024
dc.l 21*1024,22*1024,23*1024,24*1024
dc.l 25*1024,26*1024,27*1024,28*1024
dc.l 29*1024,30*1024,31*1024,32*1024
dc.l 33*1024
dcb.l MaxWall-34,0
; Level 2 -----------------------------------------------------
dc.l 512
dc.l 04*512,05*512,06*512,07*512
dc.l 10*512,11*512,12*512,13*512
dc.l 16*512,17*512,18*512,19*512
dc.l 22*512,23*512,24*512,25*512
dc.l 28*512,29*512,30*512,31*512
dc.l 32*512,33*512,34*512,35*512
dc.l 36*512,37*512,38*512,39*512
dc.l 40*512,41*512,42*512,43*512
dc.l 46*512
dcb.l MaxWall-34,0
; Level 3 -----------------------------------------------------
dc.l 512
dc.l 02*512,03*512,05*512,06*512
dc.l 08*512,09*512,11*512,12*512
dc.l 14*512,15*512,17*512,18*512
dc.l 20*512,21*512,23*512,24*512
dc.l 26*512,27*512,29*512,30*512
dc.l 32*512,33*512,35*512,36*512
dc.l 38*512,39*512,41*512,42*512
dc.l 44*512,45*512,47*512,48*512
dc.l 50*512
dcb.l MaxWall-34,0
; Level 4 -----------------------------------------------------
dc.l 512
dc.l 04*512,05*512,11*256,06*512
dc.l 07*512,08*512,17*256,09*512
dc.l 10*512,11*512,23*256,12*512
dc.l 14*512
dcb.l MaxWall-14,0
; Level 5 -----------------------------------------------------
dc.l 512
dc.l 02*512,04*512,05*512,05*512+256
dc.l 08*512,09*512,12*512,13*512
dc.l 16*512,18*512,19*512,19*512+256
dc.l 22*512,23*512,26*512,27*512
dc.l 30*512,31*512,32*512,33*512
dc.l 34*512,35*512,36*512,37*512
dc.l 40*512,41*512,42*512,43*512
dc.l 44*512,45*512,46*512,47*512
dc.l 50*512,51*512,51*512+256,51*512+256+128
dc.l 52*512,52*512+256,53*512,53*512+256
dc.l 54*512,55*512,55*512+256,55*512+256+128
dc.l 56*512,56*512+256,57*512,57*512+256
dc.l 60*512
dcb.l MaxWall-50,0
Wall_Type ; Level 1 -----------------------------------------------------
dc.w WT_Start
dc.w WT_Left,WT_Left,WT_Left,WT_Left
dc.w WT_Right,WT_Right,WT_Right,WT_Right
dc.w WT_Left,WT_Left,WT_Right,WT_Right
dc.w WT_Left,WT_Left,WT_Right,WT_Right
dc.w WT_Up,WT_Up,WT_Down,WT_Down
dc.w WT_Up,WT_Up,WT_Down,WT_Down
dc.w WT_Up,WT_Down,WT_Up,WT_Down
dc.w WT_Up,WT_Down,WT_Up,WT_Down
dc.w WT_Finish
dcb.w MaxWall-34,0
; Level 2 -----------------------------------------------------
dc.w WT_Start
dc.w WT_Left,WT_Up,WT_Right,WT_Down
dc.w WT_Up,WT_Left,WT_Down,WT_Right
dc.w WT_Right,WT_Up,WT_Down,WT_Left
dc.w WT_Down,WT_Left,WT_Right,WT_Up
dc.w WT_Left,WT_Up,WT_Right,WT_Down
dc.w WT_Up,WT_Left,WT_Down,WT_Right
dc.w WT_Right,WT_Up,WT_Down,WT_Left
dc.w WT_Down,WT_Left,WT_Right,WT_Up
dc.w WT_Finish
dcb.w MaxWall-34,0
; Level 3 -----------------------------------------------------
dc.w WT_Start
dc.w WT_Right,WT_Up,WT_Left,WT_Down
dc.w WT_Right,WT_Up,WT_Left,WT_Down
dc.w WT_Left,WT_Up,WT_Right,WT_Down
dc.w WT_Left,WT_Up,WT_Right,WT_Down
dc.w WT_Right,WT_Down,WT_Left,WT_Up
dc.w WT_Right,WT_Down,WT_Left,WT_Up
dc.w WT_Left,WT_Down,WT_Right,WT_Up
dc.w WT_Left,WT_Down,WT_Right,WT_Up
dc.w WT_Finish
dcb.w MaxWall-34,0
; Level 4 -----------------------------------------------------
dc.w WT_Start
dc.w WT_Down,WT_Up,WT_Left,WT_Down
dc.w WT_Up,WT_Down,WT_Right,WT_Up
dc.w WT_Down,WT_Up,WT_Left,WT_Right
dc.w WT_Finish
dcb.w MaxWall-14,0
; Level 5 -----------------------------------------------------
dc.w WT_Start
dc.w WT_Left,WT_Down,WT_Up,WT_Right
dc.w WT_Left,WT_Right,WT_Left,WT_Right
dc.w WT_Left,WT_Down,WT_Up,WT_Right
dc.w WT_Down,WT_Up,WT_Down,WT_Up
dc.w WT_Right,WT_Right,WT_Down,WT_Up
dc.w WT_Left,WT_Left,WT_Up,WT_Up
dc.w WT_Right,WT_Right,WT_Up,WT_Down
dc.w WT_Left,WT_Left,WT_Up,WT_Up
dc.w WT_Left,WT_Down,WT_Up,WT_Right
dc.w WT_Left,WT_Right,WT_Left,WT_Right
dc.w WT_Left,WT_Down,WT_Up,WT_Right
dc.w WT_Down,WT_Up,WT_Down,WT_Up
dc.w WT_Finish
dcb.w MaxWall-50,0
; *****************************************************************************
; Constant data
; *****************************************************************************
ALIGNLONG
Type_Bitmap dc.l wt_start ; Pointers to bitmaps
dc.l wt_finish
dc.l wt_left
dc.l wt_right
dc.l wt_up
dc.l wt_down
Type_Hole dc.w 0,0,159,127 ; WT_Start
dc.w 0,0,159,127 ; WT_Finish
dc.w 80,0,159,127 ; WT_Left
dc.w 0,0,79,127 ; WT_Right
dc.w 0,64,159,127 ; WT_Up
dc.w 0,0,159,63 ; WT_Down
Ship_Anim dc.l Ship01,Ship02,Ship03,Ship04,Ship05 ; Pointers to
dc.l Ship06,Ship07,Ship08,Ship09,Ship10 ; animation
dc.l Ship11,Ship12,Ship13,Ship14,Ship15 ; frames
dc.l Ship16,Ship17,Ship18,Ship19,Ship20 ;
dc.l Ship21,Ship22,Ship23,Ship24,Ship25 ;
Shadow_Anim dc.l Shadow01,Shadow02,Shadow03,Shadow04 ; Pointers to
dc.l Shadow05 ; anim frames
Coll_Bounds dc.w -21,-10,20,9, -20,-10,20,9 ; Collision
dc.w -19,-10,20,9, -20,-10,20,9 ; boundaries
dc.w -20,-10,21,9, -21,-8,20,7 ; for player ship
dc.w -19,-8,20,7, -19,-8,19,6
dc.w -20,-8,19,7, -20,-8,21,7
dc.w -20,-7,21,7, -19,-7,20,6
dc.w -19,-7,19,6, -20,-7,19,6
dc.w -21,-7,20,7, -20,-12,20,10
dc.w -19,-12,20,9, -19,-12,20,8
dc.w -20,-12,19,9, -20,-12,20,10
dc.w -20,-12,20,13, -19,-12,19,12
dc.w -19,-12,20,11, -19,-12,19,12
dc.w -20,-12,20,13
Raw2ASCII dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 00..0F
dc.b 81,87,69,82,84,89,85,73,79,80,0,0,0,0,0,0 ; 10..1F
dc.b 65,83,68,70,71,72,74,75,76,00,0,0,0,0,0,0 ; 20..2F
dc.b 00,90,88,67,86,66,78,77,00,00,0,0,0,0,0,0 ; 30..3F
dc.b 32 ; 40
; *****************************************************************************
; Graphics, text, etc...
; *****************************************************************************
ALIGNLONG
incdir "fantasy:tunn3l/inc/"
TxtLut incbin "Txt.LUT" ; 160x128x2 Texture LookUpTable
WallLut_S incbin "Wall_S.LUT" ; }
WallLut_X incbin "Wall_X.LUT" ; }- 2048x4 Wall LookUpTable
WallLut_Y incbin "Wall_Y.LUT" ; }
txt incbin "TunnelTxt.CKY" ; 256x256 tunnel texture
Ship01 incbin "Ship01.CKY" ; 48x25 ship images
Ship02 incbin "Ship02.CKY" ;
Ship03 incbin "Ship03.CKY" ;
Ship04 incbin "Ship04.CKY" ;
Ship05 incbin "Ship05.CKY" ;
Ship06 incbin "Ship06.CKY" ;
Ship07 incbin "Ship07.CKY" ;
Ship08 incbin "Ship08.CKY" ;
Ship09 incbin "Ship09.CKY" ;
Ship10 incbin "Ship10.CKY" ;
Ship11 incbin "Ship11.CKY" ;
Ship12 incbin "Ship12.CKY" ;
Ship13 incbin "Ship13.CKY" ;
Ship14 incbin "Ship14.CKY" ;
Ship15 incbin "Ship15.CKY" ;
Ship16 incbin "Ship16.CKY" ;
Ship17 incbin "Ship17.CKY" ;
Ship18 incbin "Ship18.CKY" ;
Ship19 incbin "Ship19.CKY" ;
Ship20 incbin "Ship20.CKY" ;
Ship21 incbin "Ship21.CKY" ;
Ship22 incbin "Ship22.CKY" ;
Ship23 incbin "Ship23.CKY" ;
Ship24 incbin "Ship24.CKY" ;
Ship25 incbin "Ship25.CKY" ;
Shadow01 incbin "Shadow01.CKY" ; 48x25 shadow images
Shadow02 incbin "Shadow02.CKY" ;
Shadow03 incbin "Shadow03.CKY" ;
Shadow04 incbin "Shadow04.CKY" ;
Shadow05 incbin "Shadow05.CKY" ;
wt_start incbin "WT_Start.CKY" ; Wall graphics
wt_finish incbin "WT_Finish.CKY" ;
wt_left incbin "WT_Left.CKY" ;
wt_right incbin "WT_Right.CKY" ;
wt_up incbin "WT_Up.CKY" ;
wt_down incbin "WT_Down.CKY" ;
IntroPal incbin "IntroPal.PAL" ; Intro palette (24-bit)
GamePal incbin "GamePal.PAL" ; Game palette (24-bit)
EnginePal incbin "EnginePal.PAL" ; Engine colour palette
WhitePal dcb.l 256,$00ffffff ; Totally white palette
TempPal dcb.l 256,$00000000 ; Temporary palette for fades
IntroWarp incbin "IntroWarp.LUT" ; Warp LookUpTable
IntroFont incbin "IntroFont.RAW" ; Intro font graphics
ChunkyFont incbin "ChunkyFont.CKY" ; Game font
txt_track dc.b "TRACK",0 ; Texts
txt_complete dc.b "COMPLETE",0
txt_out dc.b "OUT",0
txt_of dc.b "OF",0
txt_time dc.b "TIME",0
txt_ships dc.b "SHIPS",0
txt_press dc.b "PRESS",0
txt_fire dc.b "FIRE",0
txt_race dc.b "RACE",0
txt_over dc.b "OVER",0
txt_best dc.b "BEST",0
txt_pause dc.b "PAUSE",0
itxt_0 dc.b " ZERO GRAVITY",0 ; Intro texts
itxt_1 dc.b " **************",0
itxt_2 dc.b " CREATED BY",0
itxt_3 dc.b " MATTHIJS HOLLEMANS",0
itxt_4 dc.b " @ 1997",0
itxt_5 dc.b " #[[[[[[[[[[[[[[$",0
itxt_6 dc.b " \ FIRE = START _",0
itxt_7 dc.b " \ ESC = QUIT _",0
itxt_8 dc.b " &]]]]]]]]]]]]]];",0
itxt_10 dc.b " INTRO MUSIC",0
itxt_11 dc.b " ZOLTAR/DOOM",0
itxt_12 dc.b " IN-GAME MUSIC",0
itxt_13 dc.b " RADIUM",0
itxt_14 dc.b " C2P CODE BY",0
itxt_15 dc.b " JUERGEN FISCHER",0
itxt_19 dc.b " [[[[[[[[[[[[[[[",0
itxt_20 dc.b " #[[[[[[[[[[[[[[$",0
itxt_21 dc.b " \ HALL OF FAME _",0
itxt_22 dc.b " &]]]]]]]]]]]]]];",0
ian_0 dc.b " ENTER YOUR NAME",0
ian_1 dc.b " #[[[[[[[[[[[[[$",0
ian_2 dc.b " \ _",0
ian_3 dc.b " &]]]]]]]]]]]]];",0
its_0 dc.b " #[[[[[[[[[[[[[[$",0
its_1 dc.b " \ TRACK SELECT _",0
its_2 dc.b " &]]]]]]]]]]]]]];",0
its_3 dc.b " TRACK 0",0
its_4 dc.b " TIME 0:00",0
its_5 dc.b " SHIPS 0",0
its_6 dc.b " BEST TIME BY",0
its_7 dc.b "#[[[[[[[[[[[[[[[[[[$",0
its_8 dc.b "\ FIRE = PLAY _",0
its_9 dc.b "\ LEFT = PREVIOUS _",0
its_10 dc.b "\ RIGHT = NEXT _",0
its_11 dc.b "&]]]]]]]]]]]]]]]]]];",0
version dc.b "$VER: ZeroGravity 1.0 (C) 1997 Matthijs Hollemans",0
; =============================================================================
;
; C H I P D A T A
;
; =============================================================================
SECTION ChipData,DATA_C
; *****************************************************************************
; Intro copperlist
; *****************************************************************************
IntroCop
dc.l $01fc0000 ;FMODE
dc.l $01000210 ;BPLCON0 Lores, 8 planes
dc.l $01020000 ;BPLCON1
dc.l $01040000 ;BPLCON2
dc.l $01060000 ;BPLCON3
dc.l $01080000 ;BPL1MOD
dc.l $010a0000 ;BPL2MOD
dc.l $010c0000 ;BPLCON4
dc.l $008e2c81 ;
dc.l $00902cc1 ;
dc.l $00920038 ;
dc.l $009400d0 ;
IntroCopBpl ; Bitplane pointers
dc.l $00e00000,$00e20000
dc.l $00e40000,$00e60000
dc.l $00e80000,$00ea0000
dc.l $00ec0000,$00ee0000
dc.l $00f00000,$00f20000
dc.l $00f40000,$00f60000
dc.l $00f80000,$00fa0000
dc.l $00fc0000,$00fe0000
IntroCopCol ; Colour registers (24 bit HL)
dc.l $01060c40 ; Bank0, Hi 12-bits
COL32
dc.l $01060e40 ; Bank0, Lo 12-bits
COL32
dc.l $01062c40 ; Bank1, Hi 12-bits
COL32
dc.l $01062e40 ; Bank1, Lo 12-bits
COL32
dc.l $01064c40 ; etc...
COL32
dc.l $01064e40
COL32
dc.l $01066c40
COL32
dc.l $01066e40
COL32
dc.l $01068c40
COL32
dc.l $01068e40
COL32
dc.l $0106ac40
COL32
dc.l $0106ae40
COL32
dc.l $0106cc40
COL32
dc.l $0106ce40
COL32
dc.l $0106ec40
COL32
dc.l $0106ee40
COL32
IntroCopSpr
dc.l $01200000,$01220000,$01240000,$01260000
dc.l $01280000,$012a0000,$012c0000,$012e0000
dc.l $01300000,$01320000,$01340000,$01360000
dc.l $01380000,$013a0000,$013c0000,$013e0000
IntroCopRainbow
dc.l $2c0ffffe,$1060c40,$1be0346,$1060e40,$1be07b0 ; StartY=44
dc.l $2d0ffffe,$1060c40,$1be0345,$1060e40,$1be06ae
dc.l $2e0ffffe,$1060c40,$1be0345,$1060e40,$1be059d
dc.l $2f0ffffe,$1060c40,$1be0345,$1060e40,$1be048c
dc.l $300ffffe,$1060c40,$1be0345,$1060e40,$1be047b
dc.l $310ffffe,$1060c40,$1be0345,$1060e40,$1be0369
dc.l $320ffffe,$1060c40,$1be0345,$1060e40,$1be0258
dc.l $330ffffe,$1060c40,$1be0345,$1060e40,$1be0247
dc.l $340ffffe,$1060c40,$1be0345,$1060e40,$1be0136
dc.l $350ffffe,$1060c40,$1be0345,$1060e40,$1be0025
dc.l $360ffffe,$1060c40,$1be0345,$1060e40,$1be0013
dc.l $370ffffe,$1060c40,$1be0245,$1060e40,$1be0f02
dc.l $380ffffe,$1060c40,$1be0235,$1060e40,$1be0ef1
dc.l $390ffffe,$1060c40,$1be0235,$1060e40,$1be0de0
dc.l $3a0ffffe,$1060c40,$1be0234,$1060e40,$1be0dde
dc.l $3b0ffffe,$1060c40,$1be0234,$1060e40,$1be0ccd
dc.l $3c0ffffe,$1060c40,$1be0234,$1060e40,$1be0bbc
dc.l $3d0ffffe,$1060c40,$1be0234,$1060e40,$1be0bab
dc.l $3e0ffffe,$1060c40,$1be0234,$1060e40,$1be0a9a
dc.l $3f0ffffe,$1060c40,$1be0234,$1060e40,$1be0988
dc.l $400ffffe,$1060c40,$1be0234,$1060e40,$1be0987
dc.l $410ffffe,$1060c40,$1be0234,$1060e40,$1be0876
dc.l $420ffffe,$1060c40,$1be0234,$1060e40,$1be0765
dc.l $430ffffe,$1060c40,$1be0234,$1060e40,$1be0754
dc.l $440ffffe,$1060c40,$1be0234,$1060e40,$1be0642
dc.l $450ffffe,$1060c40,$1be0234,$1060e40,$1be0531
dc.l $460ffffe,$1060c40,$1be0234,$1060e40,$1be0420
dc.l $470ffffe,$1060c40,$1be0233,$1060e40,$1be041f
dc.l $480ffffe,$1060c40,$1be0233,$1060e40,$1be030d
dc.l $490ffffe,$1060c40,$1be0223,$1060e40,$1be02fc
dc.l $4a0ffffe,$1060c40,$1be0223,$1060e40,$1be02eb
dc.l $4b0ffffe,$1060c40,$1be0223,$1060e40,$1be01da
dc.l $4c0ffffe,$1060c40,$1be0223,$1060e40,$1be00c9
dc.l $4d0ffffe,$1060c40,$1be0223,$1060e40,$1be00b7
dc.l $4e0ffffe,$1060c40,$1be0123,$1060e40,$1be0fa6
dc.l $4f0ffffe,$1060c40,$1be0123,$1060e40,$1be0e95
dc.l $500ffffe,$1060c40,$1be0123,$1060e40,$1be0d84
dc.l $510ffffe,$1060c40,$1be0123,$1060e40,$1be0d73
dc.l $520ffffe,$1060c40,$1be0123,$1060e40,$1be0c61
dc.l $530ffffe,$1060c40,$1be0123,$1060e40,$1be0b50
dc.l $540ffffe,$1060c40,$1be0122,$1060e40,$1be0b5f
dc.l $550ffffe,$1060c40,$1be0122,$1060e40,$1be0a4e
dc.l $560ffffe,$1060c40,$1be0122,$1060e40,$1be093c
dc.l $570ffffe,$1060c40,$1be0122,$1060e40,$1be092b
dc.l $580ffffe,$1060c40,$1be0122,$1060e40,$1be081a
dc.l $590ffffe,$1060c40,$1be0122,$1060e40,$1be0709
dc.l $5a0ffffe,$1060c40,$1be0112,$1060e40,$1be07f8
dc.l $5b0ffffe,$1060c40,$1be0112,$1060e40,$1be06e6
dc.l $5c0ffffe,$1060c40,$1be0112,$1060e40,$1be05d5
dc.l $5d0ffffe,$1060c40,$1be0112,$1060e40,$1be04c4
dc.l $5e0ffffe,$1060c40,$1be0112,$1060e40,$1be04b3
dc.l $5f0ffffe,$1060c40,$1be0112,$1060e40,$1be03a2
dc.l $600ffffe,$1060c40,$1be0112,$1060e40,$1be0290
dc.l $610ffffe,$1060c40,$1be0111,$1060e40,$1be028f
dc.l $620ffffe,$1060c40,$1be0111,$1060e40,$1be017e
dc.l $630ffffe,$1060c40,$1be0111,$1060e40,$1be006d
dc.l $640ffffe,$1060c40,$1be0111,$1060e40,$1be005b
dc.l $650ffffe,$1060c40,$1be0011,$1060e40,$1be0f4a
dc.l $660ffffe,$1060c40,$1be0011,$1060e40,$1be0e39
dc.l $670ffffe,$1060c40,$1be0011,$1060e40,$1be0d28
dc.l $680ffffe,$1060c40,$1be0011,$1060e40,$1be0d27
dc.l $690ffffe,$1060c40,$1be0011,$1060e40,$1be0c15
dc.l $6a0ffffe,$1060c40,$1be0011,$1060e40,$1be0b04
dc.l $6b0ffffe,$1060c40,$1be0001,$1060e40,$1be0bf3
dc.l $6c0ffffe,$1060c40,$1be0001,$1060e40,$1be0ae2
dc.l $6d0ffffe,$1060c40,$1be0001,$1060e40,$1be09d1
dc.l $6e0ffffe,$1060c40,$1be0000,$1060e40,$1be09cf
dc.l $6f0ffffe,$1060c40,$1be0000,$1060e40,$1be08be
dc.l $700ffffe,$1060c40,$1be0000,$1060e40,$1be07ad
dc.l $710ffffe,$1060c40,$1be0000,$1060e40,$1be079c
dc.l $720ffffe,$1060c40,$1be0000,$1060e40,$1be068a
dc.l $730ffffe,$1060c40,$1be0000,$1060e40,$1be0579
dc.l $740ffffe,$1060c40,$1be0000,$1060e40,$1be0468
dc.l $750ffffe,$1060c40,$1be0000,$1060e40,$1be0457
dc.l $760ffffe,$1060c40,$1be0000,$1060e40,$1be0346
dc.l $770ffffe,$1060c40,$1be0000,$1060e40,$1be0234
dc.l $780ffffe,$1060c40,$1be0000,$1060e40,$1be0223
dc.l $790ffffe,$1060c40,$1be0000,$1060e40,$1be0112
dc.l $7a0ffffe,$1060c40,$1be0000,$1060e40,$1be0001
dc.l $7b0ffffe,$1060c40,$1be0000,$1060e40,$1be0000
dc.l $ac0ffffe,$1060c40,$1be098b,$1060e40,$1be0ebc ; Restore COL31
IntroCopEnd
dc.l $fffffffe ; End of copperlist
; *****************************************************************************
; Chip graphics, music, etc...
; *****************************************************************************
ALIGNQUAD
SpriteData dc.l 0,0,0,0 ; Empty sprite
IntroPic incbin "Intro.RAW" ; 320x256x64 Intro picture
GameMusic incbin "GameMusic.MOD" ; In-game music module
IntroMusic incbin "IntroMusic.MOD" ; Intro music module
; *****************************************************************************
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment