mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-02-28 12:29:59 +00:00
Added sound generator, and a godmode tester for it.
This commit is contained in:
parent
8851d88415
commit
e6aae21937
@ -2432,6 +2432,7 @@ class A2PackPartitions
|
||||
assembleCode("fontEngine", "src/font/")
|
||||
assembleCode("tileEngine", "src/tile/")
|
||||
assembleCode("marks", "src/marks/")
|
||||
assembleCode("sound", "src/sound/")
|
||||
assembleCode("gen_mapSpecials", "src/mapScripts/")
|
||||
assembleCode("gen_mapExits", "src/mapScripts/")
|
||||
|
||||
|
12
Platform/Apple/virtual/src/include/sound.i
Normal file
12
Platform/Apple/virtual/src/include/sound.i
Normal file
@ -0,0 +1,12 @@
|
||||
;****************************************************************************************
|
||||
; Copyright (C) 2021 The 8-Bit Bunch. Licensed under the Apache License, Version 1.1
|
||||
; (the "License"); you may not use this file except in compliance with the License.
|
||||
; You may obtain a copy of the License at <http://www.apache.org/licenses/LICENSE-1.1>.
|
||||
; Unless required by applicable law or agreed to in writing, software distributed under
|
||||
; the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
||||
; ANY KIND, either express or implied. See the License for the specific language
|
||||
; governing permissions and limitations under the License.
|
||||
;****************************************************************************************
|
||||
|
||||
; in main LC, bank 1
|
||||
genSound = $FF80
|
@ -1448,8 +1448,6 @@ def _combat_zoneEncounter(s_encZone)#1
|
||||
is TYPE_ENEMY
|
||||
if enemyCombatTurn(p); combatPause(); fin
|
||||
break
|
||||
otherwise
|
||||
brk()
|
||||
wend
|
||||
fin
|
||||
p = p=>p_combatNext
|
||||
|
@ -22,6 +22,8 @@ const fontEngine = $EC00 // main mem LC
|
||||
const fontEngineLen = $F00 // really a bit less, but this leaves space for debug code
|
||||
const fontData = $FB00 // main mem LC
|
||||
const fontDataLen = $4FA // really only $474, but we need to fill all gaps
|
||||
const soundCode = $FF80 // main mem LC
|
||||
const soundLen = $7A // FF80.FFF9
|
||||
|
||||
const expandVec = $200 // aux mem (only for raycaster)
|
||||
const expandMax = $3600 // max size of unsplit expander
|
||||
@ -179,13 +181,14 @@ end
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Load and display the title screen, set up everything in memory
|
||||
def _startup()#1
|
||||
word pEngine, pFont, pMarks, pExpand, expanderSize
|
||||
word pEngine, pFont, pMarks, pExpand, expanderSize, pSound
|
||||
|
||||
puts("Loading game.\n")
|
||||
|
||||
auxMmgr(FREE_MEMORY, $800) // was temporarily reserved by gameloop to keep diskops bytecode out
|
||||
|
||||
// Allocate and permanently lock mem for the font engine and its font (up in LC ram)
|
||||
// Also we can load the sound generator now.
|
||||
mmgr(START_LOAD, 1) // partition 1 is where code lives
|
||||
mmgr(SET_MEM_TARGET, fontEngine)
|
||||
mmgr(REQUEST_MEMORY, fontEngineLen)
|
||||
@ -198,6 +201,7 @@ def _startup()#1
|
||||
// Load them into lo mem
|
||||
pEngine = mmgr(QUEUE_LOAD, CODE_FONT_ENGINE<<8 | RES_TYPE_CODE)
|
||||
pFont = mmgr(QUEUE_LOAD, 1<<8 | RES_TYPE_FONT)
|
||||
pSound = mmgr(QUEUE_LOAD, CODE_SOUND<<8 | RES_TYPE_CODE)
|
||||
mmgr(FINISH_LOAD, 0)
|
||||
|
||||
// Relocate font engine and font data to their final spots up in the language card
|
||||
@ -207,7 +211,11 @@ def _startup()#1
|
||||
// Tell the font engine where to find its font
|
||||
setFont(fontData)
|
||||
|
||||
// Relocate the sound routine to its proper place
|
||||
memcpy(pSound, soundCode, soundLen, 0)
|
||||
|
||||
// Load the title screen and show it.
|
||||
pResourceIndex = 0 // special case - can't load resourceIndex yet because future expander
|
||||
loadFrameImg(1) // title screen is fixed at #1
|
||||
^$C050 // graphics
|
||||
^$C057 // hi-res
|
||||
@ -247,6 +255,7 @@ def _startup()#1
|
||||
mmgr(FREE_MEMORY, pExpand)
|
||||
|
||||
// To reduce fragmentation, load the resource index in the lowest possible aux mem spot.
|
||||
// Note: this has to be done after the expander, since it temporarily uses this space.
|
||||
pResourceIndex = $800
|
||||
auxMmgr(SET_MEM_TARGET, pResourceIndex)
|
||||
auxMmgr(QUEUE_LOAD, CODE_RESOURCE_INDEX<<8 | RES_TYPE_CODE)
|
||||
|
@ -24,7 +24,6 @@ import gamelib
|
||||
predef beep()#0
|
||||
predef benchPlayer()#0
|
||||
predef blit(isAux, srcData, dstScreenPtr, nLines, lineSize)#0
|
||||
predef brk()#0
|
||||
predef buildString()#0
|
||||
predef buySell(storeCode, profitRatio)#0
|
||||
predef calcPlayerArmor(player)#0
|
||||
@ -33,6 +32,7 @@ import gamelib
|
||||
predef callProRWTS(cmdPlusOpenFlg, filename, addr, size)#1
|
||||
predef charToUpper(c)#1
|
||||
predef checkEncounter(x, y, force)#0
|
||||
predef clampByte(val)#1
|
||||
predef clearEncounterZones()#0
|
||||
predef clearPortrait()#0
|
||||
predef clearWindow()#0
|
||||
@ -58,6 +58,7 @@ import gamelib
|
||||
predef forEach(p, do)#0
|
||||
predef forSome(p, sel, do)#0
|
||||
predef fullAddItem(pItem, doit)#1
|
||||
predef genSound(dnnoise, dnvelo, dndelay, upnoise, upvelo, updelay, negdur)#0
|
||||
predef getCharResponse()#1
|
||||
predef getCursor()#2
|
||||
predef getDir()#1
|
||||
|
@ -220,6 +220,7 @@ asm _defs
|
||||
!source "../../include/plasma.i"
|
||||
!source "../../include/mem.i"
|
||||
!source "../../include/fontEngine.i"
|
||||
!source "../../include/sound.i"
|
||||
!source "../../include/prorwts.i"
|
||||
|
||||
; Optional debug printing support
|
||||
@ -826,11 +827,10 @@ asm getFloppyFlg()#1
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Execute a monitor breakpoint
|
||||
export asm brk()#0
|
||||
bit setText
|
||||
bit page1
|
||||
brk
|
||||
// Generate a sound on the Apple II speaker
|
||||
export asm genSound(dnnoise, dnvelo, dndelay, upnoise, upvelo, updelay, dur)#0
|
||||
+asmPlasmNoRet 7
|
||||
jmp genSound
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1703,6 +1703,9 @@ export def lookupResourcePart(sectionNum, resourceNum)#1
|
||||
word ptr
|
||||
byte n, i
|
||||
|
||||
// Special case: main frame img laods before resource index
|
||||
if !pResourceIndex; return 1; fin
|
||||
|
||||
// Skip to the requested section (starting just after version num)
|
||||
ptr = pResourceIndex
|
||||
while sectionNum > 0
|
||||
@ -1712,7 +1715,7 @@ export def lookupResourcePart(sectionNum, resourceNum)#1
|
||||
|
||||
// And grab the number from that section's table
|
||||
n = readAuxByte(ptr)
|
||||
if resourceNum > n; fatal("lkupFail1"); fin
|
||||
if resourceNum > n; fatal("lkup1"); fin
|
||||
n = readAuxByte(ptr + resourceNum)
|
||||
|
||||
// If resource is on the current map's disk, prefer that
|
||||
@ -2088,7 +2091,7 @@ def initMap(x, y, dir)#0
|
||||
|
||||
// Load the map
|
||||
curMapPartition = lookupResourcePart(mapIs3D+1, mapNum)
|
||||
if !curMapPartition; fatal("lkupFail2"); fin
|
||||
if !curMapPartition; fatal("lkup2"); fin
|
||||
mmgr(START_LOAD, curMapPartition)
|
||||
pCurMap = mmgr(QUEUE_LOAD, mapNum<<8 | (RES_TYPE_2D_MAP+mapIs3D))
|
||||
mmgr(FINISH_LOAD, 0)
|
||||
@ -2721,7 +2724,7 @@ export def setPortrait(portraitNum)#0
|
||||
|
||||
// Load the portrait image and display it
|
||||
part = lookupResourcePart(3, portraitNum)
|
||||
if !part; fatal("lkupFail2"); fin
|
||||
if !part; fatal("lkup3"); fin
|
||||
// Commented out below, because it prevents cycling thru all portraits (in god mode)
|
||||
// NO: if part > 1; part = curMapPartition; fin // Look on disk 1 or current disk only
|
||||
mmgr(START_LOAD, part)
|
||||
@ -3201,6 +3204,7 @@ def initCmds()#0
|
||||
cmdTbl['G'] = @cheatCmd // next ground
|
||||
cmdTbl['&'] = @printMem // print mem
|
||||
cmdTbl['^'] = @cheatCmd // edit flags
|
||||
cmdTbl['*'] = @cheatCmd // soundGen test
|
||||
fin
|
||||
|
||||
// Commands handled differently in 3D vs 2D
|
||||
@ -3555,7 +3559,7 @@ export def hisHerTheir(gender)#1
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def clampByte(val)#1
|
||||
export def clampByte(val)#1
|
||||
return max(0, min(255, val))
|
||||
end
|
||||
|
||||
|
@ -25,6 +25,8 @@ predef _addItem()#1
|
||||
predef _addPlayer()#1
|
||||
word[] funcTbl = @_cheatCmd, @_addItem, @_addPlayer
|
||||
|
||||
predef parseDecWithDefault(str, default)#1
|
||||
|
||||
asm _defs
|
||||
|
||||
; Use hi-bit ASCII for Apple II
|
||||
@ -59,6 +61,49 @@ asm readStr()#1
|
||||
rts
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def testSoundGen()#0
|
||||
word pStr, n, dur, updelay, upvelo, upnoise, dndelay, dnvelo, dnnoise, print
|
||||
^$C051; ^$C054
|
||||
updelay = 0
|
||||
upvelo = 0
|
||||
dndelay = 0
|
||||
dnvelo = 0
|
||||
upnoise = 0
|
||||
dnnoise = 0
|
||||
dur = 1000
|
||||
print = TRUE
|
||||
while TRUE
|
||||
if print
|
||||
puts("\n")
|
||||
printf3("Up: A:dly=%d B:velo=%d C:noise=%d\n", updelay, upvelo, upnoise)
|
||||
printf3("Dn: D:dly=%d E:velo=%d F:noise=%d\n", dndelay, dnvelo, dnnoise)
|
||||
printf1("Dur: G=%d\n", dur)
|
||||
fin
|
||||
puts("Noise cmd, e.g. 50G: ")
|
||||
pStr = readStr()
|
||||
if ^pStr >= 2
|
||||
print = TRUE
|
||||
n = parseDec(pStr)
|
||||
when charToUpper(^(pStr + ^pStr))
|
||||
is 'A'; updelay = n; break
|
||||
is 'B'; upvelo = n; break
|
||||
is 'C'; upnoise = clampByte(n); break
|
||||
is 'D'; dndelay = n; break
|
||||
is 'E'; dnvelo = n; break
|
||||
is 'F'; dnnoise = clampByte(n); break
|
||||
is 'G'; dur = n; break
|
||||
otherwise
|
||||
puts("Error.\n")
|
||||
wend
|
||||
else
|
||||
print = FALSE
|
||||
^$25 = ^$25 - 1
|
||||
fin
|
||||
genSound(dnnoise, dnvelo, dndelay, upnoise, upvelo, updelay, dur)
|
||||
loop
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
def parseDecWithDefault(str, default)#1
|
||||
if ^str == 0
|
||||
@ -221,6 +266,7 @@ def _cheatCmd(key)#1
|
||||
is 'Y'; nextSky(); break
|
||||
is 'G'; nextGround(); break
|
||||
is '^'; editFlags(); break
|
||||
is '*'; testSoundGen(); break
|
||||
otherwise fatal("gmcmd")
|
||||
wend
|
||||
return 0
|
||||
|
@ -0,0 +1,120 @@
|
||||
;****************************************************************************************
|
||||
; Copyright (C) 2021 The 8-Bit Bunch. Licensed under the Apache License, Version 1.1
|
||||
; (the "License"); you may not use this file except in compliance with the License.
|
||||
; You may obtain a copy of the License at <http://www.apache.org/licenses/LICENSE-1.1>.
|
||||
; Unless required by applicable law or agreed to in writing, software distributed under
|
||||
; the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
||||
; ANY KIND, either express or implied. See the License for the specific language
|
||||
; governing permissions and limitations under the License.
|
||||
;****************************************************************************************
|
||||
|
||||
; Use hi-bit ASCII for Apple II
|
||||
!convtab "../include/hiBitAscii.ct"
|
||||
|
||||
; Global definitions
|
||||
!source "../include/global.i"
|
||||
!source "../include/mem.i"
|
||||
!source "../include/sound.i"
|
||||
!source "../include/plasma.i"
|
||||
|
||||
* = genSound
|
||||
|
||||
; hardware
|
||||
spkr = $C030
|
||||
|
||||
; init
|
||||
doGenSound:
|
||||
!zone {
|
||||
; stack offsets
|
||||
.o_delay = 0
|
||||
.o_velo = 1
|
||||
.o_noise = 2
|
||||
|
||||
; variables
|
||||
.negdur = $2 ; 2 bytes
|
||||
.upx = $4
|
||||
.dnx = $5
|
||||
.pbits = $6 ; 2 bytes
|
||||
.rnd = $8
|
||||
|
||||
eor #$FF
|
||||
sta .negdur
|
||||
tya
|
||||
eor #$FF
|
||||
sta .negdur+1
|
||||
inx
|
||||
stx .upx
|
||||
inx
|
||||
inx
|
||||
inx
|
||||
stx .dnx
|
||||
|
||||
lda #$EC
|
||||
sta .pbits+1
|
||||
ldy #0
|
||||
sty .pbits ; 28 bytes
|
||||
|
||||
.cycle:
|
||||
sta spkr
|
||||
|
||||
lda .o_velo+evalStkL,x
|
||||
clc
|
||||
adc .o_delay+evalStkL,x
|
||||
sta .o_delay+evalStkL,x
|
||||
lda .o_velo+evalStkH,x
|
||||
adc .o_delay+evalStkH,x
|
||||
pha
|
||||
ror ; carry out from the addition...
|
||||
eor .o_velo+evalStkH,x ; ... should match sign of the velocity
|
||||
asl ; stach match status in carry
|
||||
pla
|
||||
bcc + ; if match, accept the result...
|
||||
lda .o_delay+evalStkH,x ; ... else over/underflow occurred; revert.
|
||||
+ sta .o_delay+evalStkH,x
|
||||
|
||||
sec
|
||||
- sbc #1
|
||||
pha
|
||||
pla
|
||||
pha
|
||||
pla
|
||||
bcs -
|
||||
|
||||
.calcnoise:
|
||||
lda .rnd
|
||||
asl ; cute trick: asl + adc #0 is a lossless rotate that also clears carry
|
||||
adc (.pbits),y
|
||||
sta .rnd
|
||||
dey
|
||||
bne .npause
|
||||
inc .pbits+1
|
||||
bne +
|
||||
ldy #$EC
|
||||
sty .pbits+1
|
||||
+ ldy #$FF
|
||||
.npause:
|
||||
and .o_noise+evalStkL,x
|
||||
sec
|
||||
- sbc #1
|
||||
pha
|
||||
pla
|
||||
pha
|
||||
pla
|
||||
bcs -
|
||||
|
||||
.flip
|
||||
cpx .dnx
|
||||
ldx .upx
|
||||
bcs +
|
||||
ldx .dnx
|
||||
+
|
||||
|
||||
.nextdur:
|
||||
inc .negdur
|
||||
bne .cycle
|
||||
inc .negdur+1
|
||||
bne .cycle
|
||||
|
||||
stop:
|
||||
rts
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user