Prepare for C64 port

This commit is contained in:
Pecusx
2023-05-05 11:29:34 +02:00
parent 569cbddfe2
commit be37772b29
3 changed files with 806 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
vic_spr0_x = $D000
vic_spr0_y = $D001
vic_spr1_x = $D002
vic_spr1_y = $D003
vic_spr2_x = $D004
vic_spr2_y = $D005
vic_spr3_x = $D006
vic_spr3_y = $D007
vic_spr4_x = $D008
vic_spr4_y = $D009
vic_spr5_x = $D00A
vic_spr5_y = $D00B
vic_spr6_x = $D00C
vic_spr6_y = $D00D
vic_spr7_x = $D00E
vic_spr7_y = $D00F
vic_spr_hi_x = $D010
vic_cr1 = $D011
vic_raster = $D012
vic_lp_x = $D013
vic_lp_y = $D014
vic_spr_ena = $D015
vic_cr2 = $D016
vic_spr_exp_y = $D017
vic_mem = $D018
vic_irq = $D019
vic_irq_ena = $D01A
vic_spr_dp = $D01B
vic_spr_mcolor = $D01C
vic_spr_exp_x = $D01D
vic_spr_ss_col = $D01E
vic_spr_sd_col = $D01F
vic_border = $D020
vic_bg_color0 = $D021
vic_bg_color1 = $D022
vic_bg_color2 = $D023
vic_bg_color3 = $D024
vic_spr_color1 = $D025
vic_spr_color2 = $D026
vic_spr0_color = $D027
vic_spr1_color = $D028
vic_spr2_color = $D029
vic_spr3_color = $D02A
vic_spr4_color = $D02B
vic_spr5_color = $D02C
vic_spr6_color = $D02D
vic_spr7_color = $D02E
+213
View File
@@ -0,0 +1,213 @@
.macro basic_start(addr)
.word upstartEnd // link address
.word 10 // line num
.byte $9e // sys
?a=0
?b=0
?c=0
?d=0
?e=0
?v = %%addr
ift ?v>=10000
?a=?v/10000
?v=?v-(?a*10000)
eif
ift ?v>=1000
?b=?v/1000
?v=?v-(?b*1000)
eif
ift ?v>=100
?c=?v/100
?v=?v-(?c*100)
eif
ift ?v>=10
?d=?v/10
?v=?v-(?d*10)
eif
?e=?v%10
dta ?a+$30,?b+$30,?c+$30,?d+$30,?e+$30
.byte 0
upstartEnd
.word 0 // empty link signals the end of the program
.endm
//
// Switch bank in VIC-II
//
// Args:
// bank: bank number to switch to. Valid values: 0-3.
//
.macro SwitchVICBank(bank)
//
// The VIC-II chip can only access 16K bytes at a time. In order to
// have it access all of the 64K available, we have to tell it to look
// at one of four banks.
//
// This is controller by bits 0 and 1 in $dd00 (PORT A of CIA #2).
//
// +------+-------+----------+-------------------------------------+
// | BITS | BANK | STARTING | VIC-II CHIP RANGE |
// | | | LOCATION | |
// +------+-------+----------+-------------------------------------+
// | 00 | 3 | 49152 | ($C000-$FFFF)* |
// | 01 | 2 | 32768 | ($8000-$BFFF) |
// | 10 | 1 | 16384 | ($4000-$7FFF)* |
// | 11 | 0 | 0 | ($0000-$3FFF) (DEFAULT VALUE) |
// +------+-------+----------+-------------------------------------+
?bits=%11
ift (%%bank==0)
?bits=%11
eli (%%bank==1)
?bits=%10
eli (%%bank==2)
?bits=%01
eli (%%bank==3)
?bits=%00
eif
//
// Set Data Direction for CIA #2, Port A to output
//
lda $dd02
and #%11111100 // Mask the bits we're interested in.
ora #$03 // Set bits 0 and 1.
sta $dd02
//
// Tell VIC-II to switch to bank
//
lda $dd00
and #%11111100
ora #?bits
sta $dd00
.endm
//
// Enter hires bitmap mode (a.k.a. standard bitmap mode)
//
.macro SetHiresBitmapMode
//
// Clear extended color mode (bit 6) and set bitmap mode (bit 5)
//
lda $d011
and #%10111111
ora #%00100000
sta $d011
//
// Clear multi color mode (bit 4)
//
lda $d016
and #%11101111
sta $d016
.endm
//
// Enter hires bitmap mode (a.k.a. standard bitmap mode)
//
.macro SetMulticolorBitmapMode
//
// Clear extended color mode (bit 6) and set bitmap mode (bit 5)
//
lda $d011
and #%10111111
ora #%00100000
sta $d011
//
// Clear multi color mode (bit 4)
//
lda $d016
ora #%00010000
sta $d016
.endm
//
// Switch location of screen memory.
//
// Args:
// address: Address relative to current VIC-II bank base address.
// Valid values: $0000-$3c00. Must be a multiple of $0400.
//
.macro SetScreenMemory(address)
//
// The most significant nibble of $D018 selects where the screen is
// located in the current VIC-II bank.
//
// +------------+-----------------------------+
// | | LOCATION* |
// | BITS +---------+-------------------+
// | | DECIMAL | HEX |
// +------------+---------+-------------------+
// | 0000XXXX | 0 | $0000 |
// | 0001XXXX | 1024 | $0400 (DEFAULT) |
// | 0010XXXX | 2048 | $0800 |
// | 0011XXXX | 3072 | $0C00 |
// | 0100XXXX | 4096 | $1000 |
// | 0101XXXX | 5120 | $1400 |
// | 0110XXXX | 6144 | $1800 |
// | 0111XXXX | 7168 | $1C00 |
// | 1000XXXX | 8192 | $2000 |
// | 1001XXXX | 9216 | $2400 |
// | 1010XXXX | 10240 | $2800 |
// | 1011XXXX | 11264 | $2C00 |
// | 1100XXXX | 12288 | $3000 |
// | 1101XXXX | 13312 | $3400 |
// | 1110XXXX | 14336 | $3800 |
// | 1111XXXX | 15360 | $3C00 |
// +------------+---------+-------------------+
//
?bits = (%%address / $0400) << 4
lda $d018
and #%00001111
ora #?bits
sta $d018
.endm
//
// Set location of bitmap.
//
// Args:
// address: Address relative to VIC-II bank address.
// Valid values: $0000 (bitmap at $0000-$1FFF)
// $2000 (bitmap at $2000-$3FFF)
//
.macro SetBitmapAddress(address)
//
// In standard bitmap mode the location of the bitmap area can
// be set to either BANK address + $0000 or BANK address + $2000
//
// By setting bit 3, we can configure which of the locations to use.
//
lda $d018
ift %%address == $0000
and #%11110111
eli %%address == $2000
ora #%00001000
eif
sta $d018
.end
+546
View File
@@ -0,0 +1,546 @@
; @com.wudsn.ide.asm.mainsourcefile=scorch.asm
;C64 8-bit Scorched Earth source code
;---------------------------------------------------
;by Tomasz 'pecus' Pecko and Pawel 'pirx' Kalinowski
;Warsaw 2000, 2001, 2002, 2003, 2009, 2012, 2013
;Miami & Warsaw 2022, 2023
;---------------------------------------------------
.def TARGET = C64 ; :)
;---------------------------------------------------
.def XCORRECTION_FOR_PM = 0
; if 1 - active x position of tanks correction fo PMG
.def FASTER_GRAF_PROCS = 0
; if 1 - activates faster graphics routines
; (direct writes to screen memory - atari only :) )
;---------------------------------------------------
opt h-f+
org $801
org [a($801)],$801
basic_start(START)
;---------------------------------------------------
.macro build
dta d"1.28" ; number of this build (4 bytes)
.endm
.macro RMTSong
lda #:1
rts ; do nothing in C64
.endm
;---------------------------------------------------
icl 'definitions.asm'
;---------------------------------------------------
FirstZpageVariable = $57
.zpvar DliColorBack .byte = FirstZpageVariable
.zpvar GradientNr .byte
.zpvar GradientColors .word
.zpvar WindChangeInRound .byte ; wind change after each turn (not round only) flag - (0 - round only, >0 - each turn)
.zpvar JoystickNumber .byte
.zpvar LazyFlag .byte ; 7 bit - run Lazy Darwin, 6 bit - run Lazy Boy or Darwin (!) after inventory, 0 - nothing
.zpvar SpyHardFlag .byte ; >$7f - run SpyHard after inventory
.zpvar Vdebug .byte ; "visual debug" flag ($00 - off, $ff - on)
.zpvar xdraw .word ;= $64 ;variable X for plot
.zpvar ydraw .word ;variable Y for plot (like in Atari Basic - Y=0 in upper right corner of the screen)
.zpvar xbyte .word
.zpvar ybyte .word
.zpvar CharCode .byte
.zpvar fontind .word
.zpvar tanknr .byte
.zpvar TankSequencePointer .byte
.zpvar oldplot .word
.zpvar xc .word
.zpvar temp .word ;temporary word for the most embeded loops only
.zpvar temp2 .word ;same as above
.zpvar modify .word ;origially used to replace self-modyfying code
.zpvar tempXROLLER .word ;same as above for XROLLER routine (used also in result display routine)
.zpvar xtempDRAW .word ;same as above for XDRAW routine
.zpvar ytempDRAW .word ;same as above for XDRAW routine
.zpvar tempor2 .word
.zpvar CreditsVScrol .byte
;--------------temps used in circle routine
.zpvar xi .word ;X (word) in draw routine
.zpvar fx .byte
.zpvar yi .word ;Y (word) in draw routine
.zpvar fy .byte
.zpvar xk .word
.zpvar fs .byte
.zpvar yc .byte ;ycircle - temporary for circle
.zpvar dx .word
.zpvar dy .word
.zpvar dd .word
.zpvar di .word
.zpvar dp .word
;----------------------------
.zpvar UnderTank1 .byte
.zpvar UnderTank2 .byte
;----------------------------
.zpvar TestFlightFlag .byte ; For AI test flights ($ff - test, $00 - standard shoot flight)
.zpvar weaponPointer .word
.zpvar dliCounter .byte
.zpvar pressTimer .byte
.zpvar NTSCcounter .byte
.zpvar IsEndOfTheFallFlag .byte ; for small speedup ground falling
.zpvar sfx_effect .byte
.zpvar RMT_blocked .byte
.zpvar ScrollFlag .byte
.zpvar SkStatSimulator .byte
.zpvar FloatingAlt .byte ; floating tank altitude
.zpvar OverTankDir .byte ; (0 go right, $ff go left) direction of bypassing tanks on screen
; --------------OPTIMIZATION VARIABLES--------------
.zpvar Force .word
.zpvar Force_ .byte ; Force is 3 bytes long
.zpvar Angle .byte
.zpvar Parachute .byte ; are you insured with parachute?
.zpvar color .byte
.zpvar Erase .byte ; if 1 only mask of the character is printed
; on the graphics screen. if 0 character is printed normally
.zpvar radius .byte
.zpvar decimal .word
.zpvar NumberOfPlayers .byte ;current number of players (counted from 1)
.zpvar Counter .byte ;temporary Counter for outside loops
.zpvar ExplosionRadius .byte
.zpvar FunkyBombCounter .byte
.zpvar ResultY .byte
.zpvar xcircle .word
.zpvar ycircle .word
.zpvar vy .word
.zpvar vy_ .word ; 4 bytes
.zpvar vx .word
.zpvar vx_ .word ; 4 bytes
.zpvar HitFlag .byte ;$ff when missile hit ground, $00 when no hit, $01-$06 tank index+1 when hit tank
.zpvar PositionOnTheList .byte ; pointer position on the list being displayed
.zpvar XHit .word
.zpvar delta .word
.zpvar HowMuchToFall .byte
.zpvar magic .word
.zpvar xtraj .word
.zpvar xtraj_ .byte ; 3 bytes
.zpvar ytraj .word
.zpvar ytraj_ .byte ; 3 bytes
.zpvar Wind .word
.zpvar Wind_ .word ; 4 bytes
.zpvar RangeLeft .word
.zpvar RangeRight .word
.zpvar NewAngle .byte
.zpvar escFlag .byte
.zpvar LineYdraw .byte
.zpvar LineXdraw .word
.zpvar plot4x4color .byte ; $00 / $ff
.zpvar Multiplier .word
.zpvar Multiplier_ .byte ; 3 bytes
.zpvar HowToDraw .byte
.zpvar gravity .byte
.zpvar LineLength .word
.zpvar tracerflag .byte
.zpvar isInventory .byte
.zpvar DifficultyLevel .byte
.zpvar goleft .byte
.zpvar OffsetDL1 .byte
.zpvar L1 .byte
HotNapalmFlag = FunkyBombCounter ; reuse variable!
;* RMT ZeroPage addresses in artwork/sfx/rmtplayr.a65
displayposition = modify
LineAddress4x4 = xcircle
;-----------------------------------------------
; libraries
;-----------------------------------------------
icl 'C64/lib/C64SYS.ASM'
icl 'C64/lib/MACRO.ASM'
;-----------------------------------------------
; variable declarations in RAM (no code)
;-----------------------------------------------
ORG PMGraph + $0300 - (variablesEnd - OneTimeZeroVariables + 1)
icl 'variables.asm'
; Game loading address
ORG $4000
WeaponFont
ins 'artwork/weapons_AW6_mod.fnt' ; 'artwork/weapons.fnt'
;--------------------------------------------------
; Game Code
;--------------------------------------------------
FirstSTART
jsr MakeDarkScreen
; one time zero variables in RAM (non zero page)
lda #0
ldy #OneTimeZeroVariablesCount-1
@ sta OneTimeZeroVariables,y
dey
bpl @-
; one time zero variables in RAM (zero page)
ldy #FirstZpageVariable
@ sta $0000,y
iny
bne @-
; initialize variables in RAM (non zero page)
ldy #initialvaluesCount-1
@ lda initialvaluesStart,y
sta variablesToInitialize,y
dey
bpl @-
; set gradient to the full LGBTIQQAAPP+ flag on start
mva #0 GradientNr ; #1 to set gradient number 2 :) (next one)
jsr SelectNextGradient.NotWind
; generate linetables
jsr GenerateLineTable
; RMT INIT
lda #$f0 ;initial value
sta RMTSFXVOLUME ;sfx note volume * 16 (0,16,32,...,240)
lda #$ff ;initial value
sta sfx_effect
RMTSong 0
VMAIN VBLinterrupt,7 ;jsr SetVBL
mva #2 chactl ; necessary for 5200
;--------------------------------------------------
; Main program of the game
icl 'game.asm'
;--------------------------------------------------
;--------------------------------------------------
.proc GetKey
; waits for pressing a key and returns pressed value in A
; when [ESC] is pressed, escFlag is set
; result: A=keycode
;--------------------------------------------------
jsr WaitForKeyRelease
@
.IF TARGET = 800
lda SKSTAT
cmp #$ff
beq checkJoyGetKey ; key not pressed, check Joy
cmp #$f7 ; SHIFT
beq checkJoyGetKey
.ELSE
lda SkStatSimulator
and #%11111110
bne checkJoyGetKey ; key not pressed, check Joy
.ENDIF
lda kbcode
cmp #@kbcode._none
beq checkJoyGetKey
and #$3f ;CTRL and SHIFT ellimination
cmp #@kbcode._esc ; 28 ; ESC
bne getkeyend
mvy #$80 escFlag
bne getkeyend
checkJoyGetKey
;------------JOY-------------
;happy happy joy joy
;check for joystick now
lda STICK0
and #$0f
cmp #$0f
beq notpressedJoyGetKey
tay
lda joyToKeyTable,y
bne getkeyend
notpressedJoyGetKey
;fire
lda STRIG0
beq JoyButton
.IF TARGET = 800 ; Select and Option key only on A800
bne checkSelectKey
checkSelectKey
lda CONSOL
and #%00000010 ; Select
beq SelectPressed
lda CONSOL
and #%00000100 ; Option
.ENDIF
bne @-
OptionPressed
lda #@kbcode._atari ; Option key
bne getkeyend
SelectPressed
lda #@kbcode._tab ; Select key
bne getkeyend
JoyButton
lda #@kbcode._ret ;Return key
getkeyend
ldy #0
sty ATRACT ; reset atract mode
mvy #sfx_keyclick sfx_effect
rts
.endp
;--------------------------------------------------
.proc getkeynowait
;--------------------------------------------------
jsr WaitForKeyRelease
lda kbcode
and #$3f ;CTRL and SHIFT ellimination
rts
.endp
;--------------------------------------------------
.proc WaitForKeyRelease
;--------------------------------------------------
mva #128-KeyRepeatSpeed pressTimer ; tricky
StillWait
bit pressTimer
bmi KeyReleased
lda STICK0
and #$0f
cmp #$0f
bne StillWait
lda STRIG0
beq StillWait
.IF TARGET = 800
lda SKSTAT
cmp #$ff
bne StillWait
lda CONSOL
and #%00000110 ; Select and Option only
cmp #%00000110
bne StillWait
.ELSE
lda SkStatSimulator
and #%11111110
beq StillWait
.ENDIF
KeyReleased
rts
.endp
;--------------------------------------------------
.proc IsKeyPressed
; result: A=0 - yes , A>0 - no
;--------------------------------------------------
lda SKSTAT
and #%00000100
beq @+
lda #1
@ and STRIG0
rts
.endp
;--------------------------------------------------
.proc DemoModeOrKey
; Waits for the key pressed if at least one human is playing.
; Otherwise, waits 3 seconds (demo mode).
;--------------------------------------------------
;check demo mode
ldx numberOfPlayers
dex
checkForHuman ; if all in skillTable other than 0 then switch to DEMO MODE
lda skillTable,x
beq peopleAreHere
dex
bpl checkForHuman
; no people, just wait a bit
;pause 150
ldy #75
jsr PauseYFrames
rts
peopleAreHere
jmp getkey ; jsr:rts
.endp
;--------------------------------------------------
MakeDarkScreen
;--------------------------------------------------
jsr PMoutofScreen ; hide P/M
mva #0 dmactls ; dark screen
; and wait one frame :)
;--------------------------------------------------
.proc WaitOneFrame
;--------------------------------------------------
lda CONSOL
and #%00000101 ; Start + Option
sne:mva #$40 escFlag
and #%00000001 ; START KEY
seq:wait ; or waitRTC ?
rts
.endp
;--------------------------------------------------
.proc PauseYFrames
; Y - number of frames to wait (divided by 2)
; pauses for maximally 510 frames (255 * 2)
;--------------------------------------------------
@ jsr WaitOneFrame
jsr WaitOneFrame
dey
bne @-
rts
.endp
;--------------------------------------------------
.proc RmtSongSelect
; starting song line 0-255 to A reg
;--------------------------------------------------
cmp #song_ingame
bne noingame ; noMusic blocks only ingame song
bit noMusic
spl:lda #song_silencio
noingame
mvx #$ff RMT_blocked
ldx #<MODUL ;low byte of RMT module to X reg
ldy #>MODUL ;hi byte of RMT module to Y reg
jsr RASTERMUSICTRACKER ;Init
mva #0 RMT_blocked
rts
.endp
;-------------------------------------------------
.proc CopyFromROM
;-------------------------------------------------
;copy from CART to RAM
; trashes: Y
; temp: source
; temp2: destination
; modify: destination-end
;usage:
; mwa #DisplayCopyRom temp
; mwa #display temp2
; mwa #DisplayCopyEnd+1 modify
; jsr CopyFromROM
ldy #0
@ lda (temp),y
sta (temp2),y
inw temp
inw temp2
cpw temp2 modify
bne @-
rts
.endp
;--------------------------------------------------
icl 'C64/interrupts.asm'
;----------------------------------------------
icl 'constants.asm'
;----------------------------------------------
icl 'C64/textproc.asm'
;----------------------------------------------
icl 'grafproc.asm'
;----------------------------------------------
icl 'weapons.asm'
;----------------------------------------------
icl 'ai.asm'
;----------------------------------------------
icl 'artwork/talk.asm'
;----------------------------------------------
TankFont
ins 'artwork/tanksv4.fnt',+0,384 ; 48 characters only
;----------------------------------------------
font4x4
ins 'artwork/font4x4s.bmp',+62
;----------------------------------------------
;RMT PLAYER loading shenaningans
icl 'artwork/sfx/rmtplayr_modified.asm'
;-------------------------------------------------
.proc CheckTankCheat
ldy #$07
lda TankNr
asl
asl
asl ; 8 chars per name
tax
@
lda CheatName,y
sec
sbc tanksnames,x
cmp #$27
bne NoCheat
inx
dey
bpl @-
YesCheat
ldx TankNr
lda TanksWeaponsTableL,x
sta temp
lda TanksWeaponsTableH,x
sta temp+1
lda #99
@ iny
sta (temp),y
cpy #(number_of_weapons - 1)
bne @-
NoCheat
rts
.endp
CheatName
dta d" 008.T"+$27
;----------------------------------------------
.proc DLIinterruptBFG
pha
lda dliCounter
bne EndofBFGDLI
lda dliColorsFore
bit random
bmi @+
lda DliColorBack
@ sta COLPF2
lda dliColorsFore
bit random
bmi @+
lda DliColorBack
@ sta COLPF1
EndofBFGDLI
inc dliCounter
pla
rti
.endp
; ------------------------
.proc BFGblink
SetDLI DLIinterruptBFG ; blinking on
ldy #50
jsr PauseYFrames
SetDLI DLIinterruptGraph ; blinking off
rts
.endp
;--------------------------------------------------
.IF * > MODUL-1
.ECHO *
.ERROR 'Code and data too long'
.ENDIF
.ECHO "Bytes left: ",$b000-*
org $b000 ;address of RMT module
MODUL
;RMT module is standard Atari binary file already
ins "artwork/sfx/scorch_str9-NTSC.rmt",+6 ;include music RMT module
MODULEND
;----------------------------------------------
icl 'constants_top.asm'
;----------------------------------------------
.ECHO "Bytes on top left: ",$bfe8-* ;ROM_SETTINGS-*
.IF target = 5200
.IF * > ROM_SETTINGS-1
.ERROR 'Code and RMT song too long to fit in 5200'
.ENDIF
org ROM_SETTINGS ; 5200 ROM settings address $bfe8
; "01234567890123456789"
.byte " scorch supersystem " ;20 characters title
.byte " ", $ff ;$BFFD == $ff means diagnostic cart, no splash screen
.word FirstSTART
.ELSE
run FirstSTART
.ENDIF