From be9dea0d677ace353cd37c2f23007bb702e4657d Mon Sep 17 00:00:00 2001 From: chrisly42 Date: Mon, 26 Dec 2022 21:50:46 +0100 Subject: [PATCH] Initial version 1.0. --- LICENSE | 2 +- README.md | 101 +- binaries/raspberry_casket.bin | Bin 0 -> 6446 bytes binaries/readme.txt | 5 + example/plastic_duff.asm | 203 ++ example/plastic_duff.exe | Bin 0 -> 6560 bytes example/readme.txt | 23 + includes/hardware/custom.i | 154 + includes/hardware/dmabits.i | 49 + original/player.asm | 5052 +++++++++++++++++++++++++++++++++ original/player.bin | Bin 0 -> 18052 bytes original/player.bin.rs | Bin 0 -> 68004 bytes original/player.i | 101 + original/readme.txt | 6 + src/drop_in_replacement.asm | 17 + src/raspberry_casket.asm | 4253 +++++++++++++++++++++++++++ 16 files changed, 9964 insertions(+), 2 deletions(-) create mode 100644 binaries/raspberry_casket.bin create mode 100644 binaries/readme.txt create mode 100644 example/plastic_duff.asm create mode 100644 example/plastic_duff.exe create mode 100644 example/readme.txt create mode 100644 includes/hardware/custom.i create mode 100644 includes/hardware/dmabits.i create mode 100644 original/player.asm create mode 100644 original/player.bin create mode 100644 original/player.bin.rs create mode 100644 original/player.i create mode 100644 original/readme.txt create mode 100644 src/drop_in_replacement.asm create mode 100755 src/raspberry_casket.asm diff --git a/LICENSE b/LICENSE index 97959b5..17313c4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 chrisly42 +Copyright (c) 2022 Chris 'platon42' Hodges Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 5850778..3da2327 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,101 @@ -# PretrackerRaspberryCasket +# Raspberry Casket A fast and small open source Pretracker replayer + +## Raspberry Casket Player V1.0 (26-Dec-2022) + +Provided by Chris 'platon42' Hodges + +Rewritten by *platon42/Desire* based on a resourced, binary identical +version of the original Pretracker V1.0 replayer binary provided +by *hitchhikr* (thanks!), originally written in C by *Pink/Abyss*. + +This version is the hard work of reverse engineering all the +offsets, removing all the C compiler crud, removing dead and +surplus code (maybe artefacts from earlier ideas that did nothing), +optimizing the code where possible. This resulted in both reduced +size of the replayer, faster sample calculation and speeding the +tick routine up significantly. + +I also added a few optional features that come in handy, such as +song-end detection and precalc progress support. + +It took me more than a month and it was not fun. + +Also: Open source. It's 2022, keeping the code closed is just not +part of the demoscene spirit (anymore?), at least for a replayer. + +Also note that this is not the final state of the source code. +I could go over many places still and try to rework them. +But I wanted the code to be out in public. + +### Verification + +The replayer has been verified on about 60 Pretracker tunes to +create an identical internal state for each tick and identical +samples (if certain optimizations switches are disabled). + +I might have introduced bugs though. If you find some problems, +please let me know under chrisly@platon42.de. Thank you. + +### Usage + +The new replayer comes as a drop-in binary replacement if you wish. +In this case you will get faster sample generation (about 12% +faster on 68000) and about 45% less CPU time spent. However, you +won't get stuff as song-end detection and precalc progress this way. +This mode uses the old CPU DMA wait that takes away 8 raster lines. + +If you want to get rid of the unnecessary waiting, you can switch +to a copper driven audio control. If you want to use the top portion +of the copperlist for this, you probably need to double buffer it. +Otherwise, you could also position the copperlist at the end of +the display and use single buffering if you call the tick routine +during the vertical blank. + +Please use the documented sizes for the `MySong` and `MyPlayer` data +structures, which are the symbols `sv_SIZEOF` and `pv_SIZEOF` +respectively (about 2K and 12K with volume table). + +The source needs two common include files to compile (`custom.i` and +`dmabits.i`). You should leave assembler optimizations enabled. + +1. (If you're using copper list mode, call `pre_PrepareCopperlist`.) +2. Call `pre_SongInit` with + - a pointer to `MySong` (`mv_SIZEOF`) in `a1` and + - the music data in `a2`. + It will return the amount of sample memory needed in `d0`. +3. Then call `pre_PlayerInit` with + - a pointer to `MyPlayer` (`pv_SIZEOF`) in `a0` + - a pointer to chip memory sample buffer in `a1` + - the pointer to `MySong` in `a2` + - a pointer to a longword for progress information or null in `a3` + This will create the samples, too. +4. After that, regularly call `pre_PlayerTick` with `MyPlayer` in `a0` + and optionally the copperlist in a1 if you're using that mode). + +### Size + +The original C compiled code was... just bad. The new binary is +about 1/3 of the original one. + +The code has been also optimized in a way that it compresses better. +The original code compressed with *Blueberry's* Shrinkler goes from +18052 bytes down to 9023 bytes. + +Raspberry Casket, depending on the features compiled in, is about +6374 bytes and goes down to ~4410 bytes (in isolation). + +So this means that the optimization is not just "on the outside". + +### Timing + +Unfortunately, the replayer is still pretty slow and has high +jitter compared to other standard music replayers. + +This means it may take up to 33 raster lines (14-19 on average) +which is significant more than a standard Protracker replayer +(the original one could take about 60 raster lines worst case and +about 34 on average!). + +Watch out for *Presto*, the [LightSpeedPlayer](https://github.com/arnaud-carre/LSPlayer) variant that should +solve this problem. \ No newline at end of file diff --git a/binaries/raspberry_casket.bin b/binaries/raspberry_casket.bin new file mode 100644 index 0000000000000000000000000000000000000000..25808b166fe8280c4f00809c0bce77ef06ec9986 GIT binary patch literal 6446 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 QufSp02mPq`7vaVK1F87${{R30 literal 0 HcmV?d00001 diff --git a/binaries/readme.txt b/binaries/readme.txt new file mode 100644 index 0000000..df340d1 --- /dev/null +++ b/binaries/readme.txt @@ -0,0 +1,5 @@ +This file "raspberry_casket.bin" can replace the original "player.bin" +provided that you used the 16 KB + 16 KB allocation for player +variables as in the original player. + +It has been assembled from src/drop_in_replacement.asm. \ No newline at end of file diff --git a/example/plastic_duff.asm b/example/plastic_duff.asm new file mode 100644 index 0000000..f66b7e7 --- /dev/null +++ b/example/plastic_duff.asm @@ -0,0 +1,203 @@ +; Framework settings + +FW_STANDALONE_FILE_MODE = 1 ; enable standalone (part testing) +FW_HD_TRACKMO_MODE = 0 ; DO NOT CHANGE (not supported for standalone mode) + +FW_MUSIC_SUPPORT = 0 +FW_MUSIC_PLAYER_CHOICE = 0 ; 0 = None, 1 = LSP, 2 = LSP_CIA, 3 = P61A, 4 = Pretracker Turbo, 5 = Pretracker Copper +FW_LMB_EXIT_SUPPORT = 1 ; allows abortion of intro with LMB +FW_MULTIPART_SUPPORT = 0 ; DO NOT CHANGE (not supported for standalone mode) +FW_DYNAMIC_MEMORY_SUPPORT = 0 ; enable dynamic memory allocation. Otherwise, use fw_ChipMemStack/End etc fields. +FW_MAX_MEMORY_STATES = 4 ; the amount of memory states +FW_TOP_BOTTOM_MEM_SECTIONS = 0 ; allow allocations from both sides of the memory +FW_64KB_PAGE_MEMORY_SUPPORT = 0 ; allow allocation of chip memory that doesn't cross the 64 KB page boundary +FW_MULTITASKING_SUPPORT = 0 ; enable multitasking +FW_ROUNDROBIN_MT_SUPPORT = 0 ; enable fair scheduling among tasks with same priority +FW_BLITTERTASK_MT_SUPPORT = 0 ; enable single parallel task during large blits +FW_MAX_VPOS_FOR_BG_TASK = 300 ; max vpos that is considered to be worth switching to a background task, if any +FW_SCRIPTING_SUPPORT = 0 ; enable simple timed scripting functions +FW_PALETTE_LERP_SUPPORT = 0 ; enable basic palette fading functions +FW_YIELD_FROM_MAIN_TOO = 0 ; adds additional code that copes with Yield being called from main code instead of task +FW_VBL_IRQ_SUPPORT = 0 ; enable custom VBL IRQ routine +FW_COPPER_IRQ_SUPPORT = 1 ; enable copper IRQ routine support +FW_AUDIO_IRQ_SUPPORT = 0 ; enable audio IRQ support (unimplemented) +FW_VBL_MUSIC_IRQ = 0 ; enable calling of VBL based music ticking (disable, if using CIA timing!) +FW_BLITTERQUEUE_SUPPORT = 0 ; enable blitter queue support +FW_A5_A6_UNTOUCHED = 1 ; speed up blitter queue if registers a5/a6 are never changed in main code + +FW_LZ4_SUPPORT = 0 ; compile in LZ4 decruncher +FW_DOYNAX_SUPPORT = 0 ; compile in doynax decruncher +FW_ZX0_SUPPORT = 0 ; compile in ZX0 decruncher + +CHIPMEM_SIZE = 4 +FASTMEM_SIZE = 4 + +; Raspberry Casket settings +PRETRACKER_SUPPORT_V1_5 = 1 +PRETRACKER_PARANOIA_MODE = 0 +PRETRACKER_DUBIOUS_PITCH_SHIFT_FOR_DELAYED_TRACK = 0 +PRETRACKER_KEEP_JUMP_TABLE = 0 +PRETRACKER_SONG_END_DETECTION = 0 +PRETRACKER_PROGRESS_SUPPORT = 0 +PRETRACKER_FASTER_CODE = 1 +PRETRACKER_VOLUME_TABLE = 1 +PRETRACKER_BUGFIX_CODE = 1 +PRETRACKER_DONT_TRASH_REGS = 0 +PRETRACKER_COPPER_OUTPUT = 1 + +DEBUG_DETAIL SET 0 + +NEWAGE_DEBUG = 1 + + include "../frameworkng/framework.i" + + STRUCTURE PartData,fw_SIZEOF + ULONG pd_Progress + ULONG pd_SamplesSize + + ULONG pd_StartVHPos + ULONG pd_MinClocks + ULONG pd_SumClocks + ULONG pd_MaxClocks + UWORD pd_SumCount + STRUCT pd_MyPlayer,pv_SIZEOF + STRUCT pd_MySong,sv_SIZEOF + LABEL pd_SIZEOF + + include "../frameworkng/framework.asm" + +entrypoint: + + IFNE PRETRACKER_COPPER_OUTPUT + lea pld_pretracker_copperlist,a0 + move.w #300,d0 + bsr pre_PrepareCopperlist + move.l d1,(a0) ; terminate copperlist + ENDC + + ;lea pd_MyPlayer(a6),a0 + lea pd_MySong(a6),a1 + move.l #pretracker_data,a2 + PUTMSG 10,<"NewInit songInit %p, %p, %p">,a0,a1,a2 + PUSHM a5/a6 + bsr pre_SongInit + POPM + PUTMSG 10,<"Return val %ld">,d0 + move.l d0,pd_SamplesSize(a6) + + CALLFW VSync + move.w fw_FrameCounter(a6),d6 + lea pd_MyPlayer(a6),a0 + move.l #lsp_samples,a1 + lea pd_MySong(a6),a2 + sub.l a3,a3 + PUTMSG 10,<"NewInit playerInit %p, %p, %p">,a0,a1,a2 + PUSHM d6/a5/a6 + bsr pre_PlayerInit + POPM + move.w fw_FrameCounter(a6),d1 + sub.w d6,d1 + PUTMSG 10,<"Return val %ld, Frames: %d">,d0,d1 + + move.l #100000,pd_MinClocks(a6) + + lea pld_copperlist,a0 + CALLFW SetCopper + + lea .track_time(pc),a0 + move.l a0,fw_CopperIRQ(a6) + +.loop moveq.l #63,d0 + and.w fw_FrameCounter(a6),d0 + bne.s .nooutput + move.l pd_SumClocks(a6),d0 + divu pd_SumCount(a6),d0 + PUTMSG 10,<"Min %d Max %d Average %d">,pd_MinClocks(a6),pd_MaxClocks(a6),d0 +.nooutput + CALLFW VSync + bra.s .loop + +.track_time + move.w #$5ff,color(a5) + move.l vposr(a5),pd_StartVHPos(a6) + PUSHM d1-d7/a0-a6 + lea pd_MyPlayer(a6),a0 + lea pld_pretracker_copperlist,a1 + bsr pre_PlayerTick + POPM + move.l vposr(a5),d0 + move.w #$f6f,color(a5) + + PUSHM d1-d4 + and.l #$1ffff,d0 + move.l pd_StartVHPos(a6),d1 + and.l #$1ffff,d1 + moveq.l #0,d3 + move.b d0,d3 + lsr.l #8,d0 + mulu #227,d0 + add.l d3,d0 + + moveq.l #0,d4 + move.b d1,d4 + lsr.l #8,d1 + mulu #227,d1 + add.l d4,d1 + PUTMSG 20,<"Startclocks %ld Clocks %ld">,d1,d0 + sub.l d1,d0 + cmp.l pd_MinClocks(a6),d0 + bge.s .nomin + move.l d0,pd_MinClocks(a6) +.nomin + cmp.l pd_MaxClocks(a6),d0 + ble.s .nomax + move.l d0,pd_MaxClocks(a6) +.nomax + add.l d0,pd_SumClocks(a6) + addq.w #1,pd_SumCount(a6) + POPM + rts + + include "../frameworkng/musicplayers/raspberry_casket.asm" + +;-------------------------------------------------------------------- + + section "pld_copper",data,chip + +pld_copperlist: + COP_MOVE diwstrt,$2c81 ; window start + COP_MOVE diwstop,$2cc1 ; window stop + COP_MOVE ddfstrt,$0038 ; bitplane start + COP_MOVE ddfstop,$00d0 ; bitplane stop + + COP_MOVE bplcon3,$0c00 +pld_fmode: + COP_MOVE fmode,$0000 ; fixes the aga modulo problem + COP_MOVE bplcon0,$0200 + + COP_MOVE color,$fff + ;dc.w $0180,$0fff,$01a2,$0eee,$01a4,$0edd,$01a6,$0e9b + ;dc.w $01a8,$0e69,$01aa,$0b78,$01ac,$0d57,$01ae,$0a56 + ;dc.w $01b0,$0a34,$01b2,$0934,$01b4,$0923,$01b6,$0612 + ;dc.w $01b8,$0211,$01ba,$0000 + + COP_WAITLINE $80 + COP_MOVE intreq,INTF_SETCLR|INTF_COPER + + COP_WAITRAST $ff,$de +pld_pretracker_copperlist + COP_END + ds.l 36 + COP_END + + ;incbin "../data/pretracker/raspberry_casket64x64.SPR" + + section "pretracker_data",data +pretracker_data: + incbin "../data/pretracker/Pink - Plastic Dove (from Coda Intro).prt" + + section "lsp_samples",data,chip +lsp_samples: + ds.b 19522 + + END \ No newline at end of file diff --git a/example/plastic_duff.exe b/example/plastic_duff.exe new file mode 100644 index 0000000000000000000000000000000000000000..5e0e4690295a503d3a915359edc9093e1a859270 GIT binary patch literal 6560 zcmV;R8DHiA00Z*?0000000093000000006201Ny;024z100vS300Zd&000L``v3kf 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 S!3sPxmk^kq_wT9z00Z(%Gm5zY literal 0 HcmV?d00001 diff --git a/example/readme.txt b/example/readme.txt new file mode 100644 index 0000000..b3abecd --- /dev/null +++ b/example/readme.txt @@ -0,0 +1,23 @@ +This is a bare-bone example on how to use the replayer. +It features Pink's song Plastic Dove (from the Coda Intro). + +Even though it features the full replayer code and tune, +the replayer including my demo framework and the song only +takes a mere 6560 bytes (shrinkled), which is even smaller +than the new streaming replayer used in Pink's new streaming +player demonstrated (closed source) in + +https://www.pouet.net/prod.php?which=91551 + +which is 6860 bytes. + +The Raspberry Casket replayer takes an average of 14 +rasterlines while Pink's new streaming player takes +only about 10 rasterlines. + +However, the song is not really busy and very short (1:35). +This means, regarding file size, this streaming format will +always lose against storing the full song data. + +But anyway, I think I will create a compact streaming +format later next year (2023), too. \ No newline at end of file diff --git a/includes/hardware/custom.i b/includes/hardware/custom.i new file mode 100644 index 0000000..b4caeeb --- /dev/null +++ b/includes/hardware/custom.i @@ -0,0 +1,154 @@ + IFND HARDWARE_CUSTOM_I +HARDWARE_CUSTOM_I SET 1 +** +** $VER: custom.i 39.1 (18.09.92) +** Includes Release 39.108 +** +** Offsets of Amiga custom chip registers +** +** (C) Copyright 1985-1992 Commodore-Amiga, Inc. +** All Rights Reserved +** + +* +* do this to get base of custom registers: +* XREF _custom; +* + +bltddat EQU $000 +dmaconr EQU $002 +vposr EQU $004 +vhposr EQU $006 +dskdatr EQU $008 +joy0dat EQU $00A +joy1dat EQU $00C +clxdat EQU $00E + +adkconr EQU $010 +pot0dat EQU $012 +pot1dat EQU $014 +potinp EQU $016 +potgor EQU potinp +serdatr EQU $018 +dskbytr EQU $01A +intenar EQU $01C +intreqr EQU $01E + +dskpt EQU $020 +dsklen EQU $024 +dskdat EQU $026 +refptr EQU $028 +vposw EQU $02A +vhposw EQU $02C +copcon EQU $02E +serdat EQU $030 +serper EQU $032 +potgo EQU $034 +joytest EQU $036 +strequ EQU $038 +strvbl EQU $03A +strhor EQU $03C +strlong EQU $03E + +bltcon0 EQU $040 +bltcon1 EQU $042 +bltafwm EQU $044 +bltalwm EQU $046 +bltcpt EQU $048 +bltbpt EQU $04C +bltapt EQU $050 +bltdpt EQU $054 +bltsize EQU $058 +bltcon0l EQU $05B ; note: byte access only +bltsizv EQU $05C +bltsizh EQU $05E + +bltcmod EQU $060 +bltbmod EQU $062 +bltamod EQU $064 +bltdmod EQU $066 + +bltcdat EQU $070 +bltbdat EQU $072 +bltadat EQU $074 + +deniseid EQU $07C +dsksync EQU $07E + +cop1lc EQU $080 +cop2lc EQU $084 +copjmp1 EQU $088 +copjmp2 EQU $08A +copins EQU $08C +diwstrt EQU $08E +diwstop EQU $090 +ddfstrt EQU $092 +ddfstop EQU $094 +dmacon EQU $096 +clxcon EQU $098 +intena EQU $09A +intreq EQU $09C +adkcon EQU $09E + +aud EQU $0A0 +aud0 EQU $0A0 +aud1 EQU $0B0 +aud2 EQU $0C0 +aud3 EQU $0D0 + +* AudChannel +ac_ptr EQU $00 ; ptr to start of waveform data +ac_len EQU $04 ; length of waveform in words +ac_per EQU $06 ; sample period +ac_vol EQU $08 ; volume +ac_dat EQU $0A ; sample pair +ac_SIZEOF EQU $10 + +bplpt EQU $0E0 + +bplcon0 EQU $100 +bplcon1 EQU $102 +bplcon2 EQU $104 +bplcon3 EQU $106 +bpl1mod EQU $108 +bpl2mod EQU $10A +bplcon4 EQU $10C +clxcon2 EQU $10E + +bpldat EQU $110 + +sprpt EQU $120 + +spr EQU $140 + +* SpriteDef +sd_pos EQU $00 +sd_ctl EQU $02 +sd_dataa EQU $04 +sd_dataB EQU $06 +sd_SIZEOF EQU $08 + +color EQU $180 + +htotal EQU $1c0 +hsstop EQU $1c2 +hbstrt EQU $1c4 +hbstop EQU $1c6 +vtotal EQU $1c8 +vsstop EQU $1ca +vbstrt EQU $1cc +vbstop EQU $1ce +sprhstrt EQU $1d0 +sprhstop EQU $1d2 +bplhstrt EQU $1d4 +bplhstop EQU $1d6 +hhposw EQU $1d8 +hhposr EQU $1da +beamcon0 EQU $1dc +hsstrt EQU $1de +vsstrt EQU $1e0 +hcenter EQU $1e2 +diwhigh EQU $1e4 +fmode EQU $1fc + + ENDC !HARDWARE_CUSTOM_I diff --git a/includes/hardware/dmabits.i b/includes/hardware/dmabits.i new file mode 100644 index 0000000..de208f5 --- /dev/null +++ b/includes/hardware/dmabits.i @@ -0,0 +1,49 @@ + IFND HARDWARE_DMABITS_I +HARDWARE_DMABITS_I SET 1 +** +** $VER: dmabits.i 39.1 (18.09.92) +** Includes Release 39.108 +** +** include file for defining dma control stuff +** +** (C) Copyright 1985-1992 Commodore-Amiga, Inc. +** All Rights Reserved +** + +* write definitions for dmaconw +DMAF_SETCLR EQU $8000 +DMAF_AUDIO EQU $000F ; 4 bit mask +DMAF_AUD0 EQU $0001 +DMAF_AUD1 EQU $0002 +DMAF_AUD2 EQU $0004 +DMAF_AUD3 EQU $0008 +DMAF_DISK EQU $0010 +DMAF_SPRITE EQU $0020 +DMAF_BLITTER EQU $0040 +DMAF_COPPER EQU $0080 +DMAF_RASTER EQU $0100 +DMAF_MASTER EQU $0200 +DMAF_BLITHOG EQU $0400 +DMAF_ALL EQU $01FF ; all dma channels + +* read definitions for dmaconr +* bits 0-8 correspnd to dmaconw definitions +DMAF_BLTDONE EQU $4000 +DMAF_BLTNZERO EQU $2000 + +DMAB_SETCLR EQU 15 +DMAB_AUD0 EQU 0 +DMAB_AUD1 EQU 1 +DMAB_AUD2 EQU 2 +DMAB_AUD3 EQU 3 +DMAB_DISK EQU 4 +DMAB_SPRITE EQU 5 +DMAB_BLITTER EQU 6 +DMAB_COPPER EQU 7 +DMAB_RASTER EQU 8 +DMAB_MASTER EQU 9 +DMAB_BLITHOG EQU 10 +DMAB_BLTDONE EQU 14 +DMAB_BLTNZERO EQU 13 + + ENDC ; HARDWARE_DMABITS_I diff --git a/original/player.asm b/original/player.asm new file mode 100644 index 0000000..7e23a52 --- /dev/null +++ b/original/player.asm @@ -0,0 +1,5052 @@ +lbL000000: dc.l songInit + dc.l playerInit + dc.l playerTick + dc.l lbC0038A2 + dc.l lbC001DAE + dc.l lbC0001E0 + + dc.b '$VER: PreTracker 1.0 (c) 2019 Abyss!',0 + dc.b $4E + dc.b $71,$4E + +lbC000040: subq.l #8,sp + movem.l d2-d7/a2/a3/a5/a6,-(sp) + movea.l ($34,sp),a3 + movea.l ($38,sp),a0 + move.w ($3E,sp),d4 + move.b (a3),d6 + move.b (3,a3),d0 + andi.b #7,d0 + move.b (3,a3),d1 + andi.b #$20,d1 + move.b d1,($2D,sp) + clr.w d7 + move.b d0,d7 + move.w d7,($2E,sp) + tst.b d0 + beq.w lbC00012C +lbC000076: lea (lbW003E8C,pc),a5 + moveq #0,d7 + andi.w #$FF,d6 + clr.w d0 + move.w d6,d1 + muls.w d0,d1 + move.l d1,d0 + asr.l #8,d0 + movea.l d0,a6 +lbC00008C: move.w d7,d1 + move.w (a5)+,d2 + clr.w d0 + move.b (1,a3),d0 + mulu.w d2,d0 + moveq #0,d2 +lbC00009A: move.b (2,a3),d2 + tst.b ($2D,sp) + bne.w lbC000142 + lsr.l #2,d0 + lsl.l #6,d2 + movea.l d2,a1 + adda.l d0,a1 +lbC0000AE: tst.w d4 + beq.b lbC000122 + move.l d7,d5 + addq.l #8,d5 + btst #0,d1 + bne.w lbC00014C + moveq #0,d2 + moveq #0,d3 + lea (lbW003E4C,pc),a2 + move.l d7,($28,sp) +lbC0000CA: add.l d5,d3 + move.b (a0,d2.l),d0 + move.w d3,d1 + moveq #11,d7 + lsr.w d7,d1 + andi.l #$FFFF,d1 + add.l d1,d1 + move.w (a2,d1.l),d1 + andi.l #$FFFF,d1 + lsl.l #5,d1 + add.l a1,d1 + lsr.l #6,d1 + move.w d2,d7 + sub.w d1,d7 + bmi.b lbC000134 + move.b (a0,d7.w),d1 + ext.w d1 + move.w d6,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + ext.w d0 + add.w d1,d0 + cmpi.w #$7F,d0 + bgt.b lbC00013E +lbC00010C: cmpi.w #$FF80,d0 + bge.b lbC000114 + moveq #-$80,d0 +lbC000114: move.b d0,(a0,d2.l) + addq.l #1,d2 + cmp.w d4,d2 + bcs.b lbC0000CA +lbC00011E: move.l ($28,sp),d7 +lbC000122: addq.l #1,d7 + cmp.w ($2E,sp),d7 + bcs.w lbC00008C +lbC00012C: movem.l (sp)+,d2-d7/a2/a3/a5/a6 + addq.l #8,sp + rts + +lbC000134: ext.w d0 + add.w a6,d0 + cmpi.w #$7F,d0 + ble.b lbC00010C +lbC00013E: moveq #$7F,d0 + bra.b lbC00010C + +lbC000142: lsl.l #8,d2 + movea.l d2,a1 + adda.l d0,a1 + bra.w lbC0000AE + +lbC00014C: moveq #0,d1 + moveq #0,d3 + lea (lbW003E4C,pc),a2 + move.l d7,($28,sp) + add.l d5,d3 + move.b (a0,d1.l),d0 + move.w d3,d2 + moveq #11,d7 + lsr.w d7,d2 + andi.l #$FFFF,d2 + add.l d2,d2 + move.w (a2,d2.l),d2 + andi.l #$FFFF,d2 + lsl.l #5,d2 + add.l a1,d2 + lsr.l #6,d2 + move.w d1,d7 + sub.w d2,d7 + bmi.b lbC0001DC +lbC000182: move.b (a0,d7.w),d2 + ext.w d2 +lbC000188: neg.w d2 + move.w d6,d7 + muls.w d2,d7 + move.l d7,d2 + asr.l #8,d2 + ext.w d0 + add.w d2,d0 + cmpi.w #$7F,d0 + ble.b lbC00019E + moveq #$7F,d0 +lbC00019E: cmpi.w #$FF80,d0 + bge.b lbC0001A6 + moveq #-$80,d0 +lbC0001A6: move.b d0,(a0,d1.l) + addq.l #1,d1 + cmp.w d4,d1 + bcc.w lbC00011E + add.l d5,d3 + move.b (a0,d1.l),d0 + move.w d3,d2 + moveq #11,d7 + lsr.w d7,d2 + andi.l #$FFFF,d2 + add.l d2,d2 + move.w (a2,d2.l),d2 + andi.l #$FFFF,d2 + lsl.l #5,d2 + add.l a1,d2 + lsr.l #6,d2 + move.w d1,d7 + sub.w d2,d7 + bpl.b lbC000182 +lbC0001DC: clr.w d2 + bra.b lbC000188 + +lbC0001E0: lea (-$24,sp),sp + movem.l d2-d7/a2/a3/a5/a6,-(sp) + movea.l ($50,sp),a1 + movea.l a1,a0 + tst.b ($9FA,a1) + bne.w lbC00122E +lbC0001F6: clr.l ($28,sp) + lea (lbW004000,pc),a2 + move.l a2,($34,sp) + clr.w d0 + moveq #$2A,d1 + mulu.w d1,d0 + move.l d0,($40,sp) + lea (lbW004484,pc),a2 + move.l a2,($38,sp) + lea (lbW000328,pc),a6 + lea (lbB003D3C,pc),a3 + move.l a3,($3C,sp) +lbC000220: movea.l ($38,a0),a2 + move.w ($2A,a0),d0 + move.w ($18,a0),d1 + cmpa.w #0,a2 + beq.w lbC000B6C +lbC000234: add.w ($30,a0),d0 + add.w ($12,a0),d0 + cmpi.w #$240,d0 + bgt.w lbC000E2A + move.w d0,($2A,a0) + add.w ($28,a0),d1 + bmi.w lbC000E38 +lbC000250: cmpi.w #$40,d1 + ble.w lbC001126 + move.w #$40,($18,a0) + moveq #$40,d1 +lbC000260: move.b ($6A,a0),d2 + move.w ($1C,a0),($2C,sp) + tst.b d2 + bne.w lbC00037A + clr.w ($30,a0) + clr.w ($28,a0) + move.w ($22,a0),d1 + blt.w lbC000EC8 + cmpi.w #$20,d1 + ble.b lbC000288 + moveq #$20,d1 +lbC000288: move.b d1,d0 + move.b d1,($68,a0) + move.w #$FFFF,($22,a0) + moveq #0,d5 + move.b (7,a2),d5 + clr.b d7 + clr.b d3 + moveq #-1,d4 + movea.l ($38,sp),a5 +lbC0002A4: move.b d0,d1 + ext.w d1 + movea.w d1,a3 + cmp.l a3,d5 + ble.w lbC00036C +lbC0002B0: movea.l ($9F6,a1),a2 + move.b ($1B,a0),d1 + subq.b #1,d1 + andi.l #$FF,d1 + addq.l #2,d1 + add.l d1,d1 + add.l d1,d1 + moveq #0,d2 + move.b d0,d2 + add.l d2,d2 + move.w (a5,d2.l),d2 + andi.l #$FFFF,d2 + movea.l (a2,d1.l),a2 + adda.l d2,a2 + move.b (a2),d1 + move.b (1,a2),d6 + andi.b #15,d6 + tst.b d1 + blt.w lbC000C88 + clr.b d2 +lbC0002EE: tst.b d3 + bne.b lbC000314 + andi.b #$3F,d1 + beq.b lbC000314 + andi.l #$FF,d1 + lsl.w #4,d1 + addi.w #$FFF0,d1 + move.w d1,($2E,a0) + move.b (a2),d1 + lsr.b #6,d1 + andi.b #1,d1 + move.b d1,($26,a0) +lbC000314: move.b (2,a2),d1 + andi.l #$FF,d6 + add.l d6,d6 + move.w (a6,d6.l),d3 + jmp (lbW000328,pc,d3.w) + +lbW000328: dc.w lbC0009AC-lbW000328,lbC000A8A-lbW000328 + dc.w lbC00088C-lbW000328,lbC00097E-lbW000328 + dc.w lbC0008A8-lbW000328,lbC000898-lbW000328 + dc.w lbC000898-lbW000328,lbC000898-lbW000328 + dc.w lbC000898-lbW000328,lbC000898-lbW000328 + dc.w lbC000A68-lbW000328,lbC00085C-lbW000328 + dc.w lbC00083C-lbW000328,lbC000898-lbW000328 + dc.w lbC000800-lbW000328,lbC000348-lbW000328 +lbC000348: addq.b #1,d0 + tst.b d1 + beq.w lbC000F62 + move.b d1,($69,a0) +lbC000354: move.b d0,($68,a0) + tst.b d2 + beq.b lbC00036E +lbC00035C: moveq #1,d7 + move.b d2,d3 +lbC000360: move.b d0,d1 + ext.w d1 + movea.w d1,a3 + cmp.l a3,d5 + bgt.w lbC0002B0 +lbC00036C: st d2 +lbC00036E: add.b ($69,a0),d2 + move.b d2,($6A,a0) + move.w ($18,a0),d1 +lbC00037A: cmpi.w #$FF,($2C,sp) + beq.w lbC000EE0 + movea.l ($3C,a0),a3 + moveq #0,d3 + move.b (4,a3),d3 + lsl.l #8,d3 + or.b (5,a3),d3 +lbC000394: move.w ($2A,a0),d0 + cmpi.b #$FF,d2 + beq.b lbC0003A4 + subq.b #1,d2 + move.b d2,($6A,a0) +lbC0003A4: move.b (12,a0),d2 + bne.w lbC000B84 +lbC0003AC: move.l ($40,a0),d4 + move.l ($5A,a0),d2 + moveq #1,d7 + cmp.l d4,d7 + beq.w lbC000E80 + tst.l d4 + beq.w lbC001C8C + subq.l #3,d4 + bne.w lbC000E42 + move.w ($46,a0),d4 + add.w ($48,a0),d4 + move.w d4,($46,a0) + cmpi.w #15,d4 + ble.w lbC000E42 + move.b ($44,a0),d5 + cmpi.b #$8E,d5 + bhi.w lbC001142 + move.b d5,d6 + addq.b #1,d6 + andi.l #$FF,d5 + add.l d5,d5 + lea (lbW003C1C,pc),a2 + move.w (a2,d5.l),d5 + andi.l #$FFFF,d5 + move.b d6,($44,a0) + sub.l d5,d2 + bmi.w lbC001150 +lbC00040C: move.l d2,($5A,a0) + lsr.w #4,d2 + addi.w #$FFF0,d4 + move.w d4,($46,a0) +lbC00041A: move.b (14,a0),d4 + beq.b lbC000432 + subq.b #1,d4 + move.b d4,(14,a0) + bne.b lbC000432 + clr.l ($5A,a0) + moveq #3,d6 + move.l d6,($40,a0) +lbC000432: mulu.w d2,d1 + move.b (6,a0),d2 + ext.w d2 + lsr.l #6,d1 + mulu.w d1,d2 + move.l d2,d1 + lsr.l #6,d1 + move.b d1,($76,a0) + move.b (13,a0),d1 + tst.w d3 + beq.w lbC000D8E + tst.b d1 + beq.w lbC000E48 + tst.b (6,a3) + beq.w lbC000E48 + andi.l #$FF,d1 + lsl.l #7,d1 + move.l d1,($34,a0) + clr.b (13,a0) + move.w ($24,a0),d4 + moveq #0,d2 + move.b (8,a3),d2 + lsl.l #8,d2 + or.b (9,a3),d2 + tst.w d4 + ble.w lbC001178 + sub.l d2,d1 + move.l d1,($34,a0) +lbC00048A: clr.w d5 + move.b (7,a3),d5 + move.w d5,($32,a0) + tst.w d4 + ble.w lbC0010A0 + add.l d2,d1 + moveq #0,d4 + move.w d3,d4 + add.l d1,d4 + moveq #0,d2 + move.b (2,a3),d2 + lsl.l #8,d2 + or.b (3,a3),d2 + cmp.l d1,d2 + bge.b lbC0004BE + moveq #0,d2 + move.b (10,a3),d2 + lsl.l #8,d2 + or.b (11,a3),d2 +lbC0004BE: sub.l d4,d2 + tst.l d2 + ble.w lbC000C4C +lbC0004C6: move.l d1,($34,a0) + move.w d1,d4 +lbC0004CC: move.w d3,($70,a0) + move.w d4,($72,a0) + moveq #0,d1 + move.w ($1C,a0),d1 + addi.l #$27F,d1 + add.l d1,d1 + add.l d1,d1 + move.l (a1,d1.l),($6C,a0) +lbC0004EA: tst.b ($26,a0) + bne.w lbC000DF4 +lbC0004F2: move.w ($20,a0),d1 + lsl.w #4,d1 + add.w ($2C,a0),d1 + add.w d1,d0 + move.w ($2E,a0),d1 + addi.w #$FFE0,d1 + add.w d1,d0 + move.w ($66,a0),d1 + bne.w lbC000E0A +lbC000510: move.w ($62,a0),d4 + move.w ($64,a0),d2 +lbC000518: move.w d2,d1 + add.w ($60,a0),d1 + move.w d1,($60,a0) + movea.w d1,a2 + moveq #0,d3 + move.w d4,d3 + cmp.l a2,d3 + bge.b lbC00053A + neg.w d2 + move.w d2,($64,a0) + move.w d4,d1 + move.w d4,($60,a0) + movea.w d4,a2 +lbC00053A: neg.l d3 + cmpa.l d3,a2 + bge.b lbC00054E + neg.w d2 + move.w d2,($64,a0) + move.w d4,d1 + neg.w d1 + move.w d1,($60,a0) +lbC00054E: asr.w #3,d1 + add.w d1,d0 +lbC000552: move.b ($77,a0),d6 + move.w ($70,a0),d3 + cmpi.w #$219,d0 + ble.w lbC000D80 + movea.w #$231,a2 + btst #2,($14,a3) + beq.w lbC0005F2 + moveq #0,d4 + move.b (10,a3),d4 + lsl.l #8,d4 + or.b (11,a3),d4 + move.w d4,d2 + movea.w d0,a2 + move.l a2,d5 + addi.l #$FFFFFDE7,d5 + asr.l #4,d5 + moveq #0,d7 + not.b d7 + and.l d7,d5 + lea (lbB003DD8,pc),a2 + move.b (a2,d5.l),d1 + move.w ($72,a0),d7 + cmpi.w #$FFFF,d7 + beq.w lbC001052 + moveq #0,d4 + move.b d1,d4 + andi.l #$FFFF,d7 + asr.l d4,d7 + move.w d7,($72,a0) + andi.l #$FFFF,d3 + asr.l d4,d3 + move.w d3,($70,a0) +lbC0005C0: tst.b d1 + beq.b lbC0005D8 + move.l ($6C,a0),d4 +lbC0005C8: moveq #0,d7 + move.w d2,d7 + add.l d7,d4 + lsr.w #1,d2 + subq.b #1,d1 + bne.b lbC0005C8 + move.l d4,($6C,a0) +lbC0005D8: lea (lbB003D6C,pc),a2 + clr.w d1 + move.b (a2,d5.l),d1 + lsl.w #4,d1 + sub.w d1,d0 + cmpi.w #$231,d0 + ble.b lbC0005F0 + move.w #$231,d0 +lbC0005F0: movea.w d0,a2 +lbC0005F2: tst.b d6 + beq.b lbC00060E + move.w ($72,a0),d0 + cmpi.w #$FFFF,d0 + beq.b lbC00060E + andi.l #$FFFF,d0 + add.l d0,($6C,a0) + clr.w ($72,a0) +lbC00060E: cmp.w (4,a0),d3 + beq.b lbC00061E + move.b #1,($77,a0) + move.w d3,(4,a0) +lbC00061E: move.l a2,d0 + add.l a2,d0 + movea.l ($34,sp),a2 + move.w (a2,d0.l),($74,a0) + move.b ($14,a0),d0 + beq.w lbC000C96 + moveq #3,d1 + cmp.l ($28,sp),d1 + bne.w lbC000AA2 +lbC00063E: tst.b ($77,a1) + bne.w lbC000CB0 +lbC000646: clr.w d0 + move.b ($76,a1),d0 + move.w d0,($DFF0A8) + move.w ($74,a1),($DFF0A6) + tst.b ($2F3,a1) + bne.w lbC000CE8 +lbC000662: clr.w d0 + move.b ($2F2,a1),d0 + move.w d0,($DFF0B8) + move.w ($2F0,a1),($DFF0B6) + tst.b ($56F,a1) + bne.w lbC000D20 +lbC00067E: clr.w d0 + move.b ($56E,a1),d0 + move.w d0,($DFF0C8) + move.w ($56C,a1),($DFF0C6) + tst.b ($7EB,a1) + beq.w lbC000D58 +lbC00069A: move.w #8,($DFF096) + move.l ($7E0,a1),($DFF0D0) + move.w ($7E4,a1),d0 + lsr.w #1,d0 + move.w d0,($DFF0D4) + move.w #0,($DFF0D8) + clr.b ($7EB,a1) + move.w ($7E8,a1),($DFF0D6) + moveq #4,d2 + move.l #$FFFFFF,d1 +lbC0006D2: move.l ($DFF004),d0 + move.l d0,($44,sp) + move.l ($44,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($44,sp) + move.l ($44,sp),d0 + cmp.l d0,d1 + beq.b lbC0006D2 + move.l ($44,sp),d1 + subq.b #1,d2 + bne.b lbC0006D2 + move.w #$800F,($DFF096) + moveq #4,d2 + move.l #$FFFFFF,d1 +lbC00070C: move.l ($DFF004),d0 + move.l d0,($48,sp) + move.l ($48,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($48,sp) + move.l ($48,sp),d0 + cmp.l d0,d1 + beq.b lbC00070C + move.l ($48,sp),d1 + subq.b #1,d2 + bne.b lbC00070C + move.w #$8001,($DFF096) + move.w ($72,a1),d0 + cmpi.w #$FFFF,d0 + beq.w lbC001756 + andi.l #$FFFF,d0 + add.l ($6C,a1),d0 + move.l d0,($DFF0A0) +lbC00075A: clr.w d0 + move.b ($76,a1),d0 + move.w d0,($DFF0A8) + move.w #$8002,($DFF096) + move.w ($2EE,a1),d0 + cmpi.w #$FFFF,d0 + beq.w lbC001742 + andi.l #$FFFF,d0 + add.l ($2E8,a1),d0 + move.l d0,($DFF0B0) +lbC00078A: clr.w d0 + move.b ($2F2,a1),d0 + move.w d0,($DFF0B8) + move.w #$8004,($DFF096) + move.w ($56A,a1),d0 + cmpi.w #$FFFF,d0 + beq.w lbC00172E + andi.l #$FFFF,d0 + add.l ($564,a1),d0 + move.l d0,($DFF0C0) +lbC0007BA: clr.w d0 + move.b ($56E,a1),d0 + move.w d0,($DFF0C8) + move.w #$8008,($DFF096) + move.w ($7E6,a1),d0 + cmpi.w #$FFFF,d0 + beq.w lbC001708 + andi.l #$FFFF,d0 + add.l ($7E0,a1),d0 + move.l d0,($DFF0D0) + clr.w d0 + move.b ($7EA,a1),d0 + move.w d0,($DFF0D8) + movem.l (sp)+,d2-d7/a2/a3/a5/a6 + lea ($24,sp),sp + rts + +lbC000800: move.b d1,d3 + lsr.b #4,d3 + addq.b #1,d0 + tst.b d3 + beq.w lbC001032 + cmpi.b #1,d3 + bne.w lbC000354 + andi.b #3,d1 + beq.w lbC001020 + andi.l #$FF,d1 + move.b (-1,a0,d1.l),d1 +lbC000826: andi.w #$FF,d1 + move.w d1,($20,a0) + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC00083C: andi.w #$FF,d1 + addq.b #1,d0 + cmpi.w #$40,d1 + bgt.w lbC000F74 + move.w d1,($18,a0) + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC00085C: moveq #0,d3 + move.b d1,d3 + cmp.l a3,d3 + bge.b lbC000898 + moveq #-1,d6 + cmp.l d4,d6 + beq.b lbC00086E + cmp.l d3,d4 + ble.b lbC000898 +lbC00086E: move.b d1,d0 + subq.b #1,d0 + move.b d0,($68,a0) + move.b d1,d0 + tst.b d7 + bne.w lbC00119E + move.b d1,($68,a0) + moveq #-1,d4 + moveq #1,d7 + move.b d2,d3 + bra.w lbC000360 + +lbC00088C: andi.l #$FF,d1 + neg.w d1 + move.w d1,($30,a0) +lbC000898: addq.b #1,d0 + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC0008A8: move.b d1,d3 + subq.b #1,d3 + clr.w d1 + move.b d3,d1 + addq.b #1,d0 + cmp.w ($2C,sp),d1 + beq.w lbC000354 + cmpi.b #$17,d3 + bhi.w lbC000354 + move.w d1,($1C,a0) + movea.l ($9F6,a1),a2 + move.w d1,d6 + moveq #$2A,d7 + mulu.w d7,d6 + movea.l ($9C,a2),a2 + adda.l d6,a2 + move.l a2,($3C,a0) + moveq #0,d6 + move.b (4,a2),d6 + lsl.l #8,d6 + or.b (5,a2),d6 + tst.l d6 + bne.w lbC0011B4 + moveq #0,d7 + move.b (12,a2),d7 + lsl.l #8,d7 + or.b (13,a2),d7 + move.l d7,($30,sp) + move.b #1,($77,a0) + andi.l #$FF,d3 + addi.l #$27F,d3 + add.l d3,d3 + add.l d3,d3 + moveq #0,d6 + move.w d7,d6 + movea.l d6,a3 + move.l (a1,d3.l),d3 + add.l a3,d3 + move.l d3,($6C,a0) + moveq #0,d6 + move.b (10,a2),d6 + lsl.l #8,d6 + or.b (11,a2),d6 + moveq #0,d3 + move.w d6,d3 + move.l d3,d7 + subq.l #1,d7 + cmp.l a3,d7 + bgt.w lbC001666 + moveq #2,d6 + move.w d6,($70,a0) + move.w #$FFFF,($72,a0) +lbC000948: move.l ($34,a0),d6 + cmp.l d6,d3 + bge.b lbC000956 + move.w #1,($24,a0) +lbC000956: clr.w ($32,a0) + moveq #0,d3 + move.b (8,a2),d3 + lsl.l #8,d3 + or.b (9,a2),d3 + sub.l d3,d6 + move.l d6,($34,a0) + move.w d1,($2C,sp) + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC00097E: addq.b #1,d0 + cmpi.b #1,d1 + beq.w lbC000FDA + cmpi.b #2,d1 + bne.w lbC000354 + clr.l ($40,a0) + clr.l ($5A,a0) + move.b #1,($5E,a0) + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC0009AC: subq.b #1,d1 + clr.w d3 + move.b d1,d3 + addq.b #1,d0 + cmp.w ($2C,sp),d3 + beq.w lbC000354 + cmpi.b #$17,d1 + bhi.w lbC000354 + move.w d3,($1C,a0) + movea.l ($9F6,a1),a2 + move.w d3,d6 + moveq #$2A,d7 + mulu.w d7,d6 + movea.l ($9C,a2),a2 + adda.l d6,a2 + move.l a2,($3C,a0) + moveq #0,d6 + move.b (4,a2),d6 + lsl.l #8,d6 + or.b (5,a2),d6 + tst.l d6 + bne.w lbC0011E4 + moveq #0,d7 + move.b (12,a2),d7 + lsl.l #8,d7 + or.b (13,a2),d7 + moveq #0,d6 + move.w d7,d6 + move.b #1,($77,a0) + andi.l #$FF,d1 + addi.l #$27F,d1 + add.l d1,d1 + add.l d1,d1 + move.l (a1,d1.l),d1 + add.l d6,d1 + move.l d1,($6C,a0) + moveq #0,d1 + move.b (10,a2),d1 + lsl.l #8,d1 + or.b (11,a2),d1 + movea.l d1,a3 + subq.l #1,a3 + cmpa.l d6,a3 + bgt.w lbC001656 + moveq #2,d1 + move.w d1,($70,a0) + move.w #$FFFF,($72,a0) +lbC000A40: clr.w d1 + move.b (7,a2),d1 + addq.w #1,d1 + move.w d1,($32,a0) + move.l d6,($34,a0) + move.w #1,($24,a0) + move.w d3,($2C,sp) +lbC000A5A: move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC000A68: move.b d1,d3 + andi.b #15,d3 + beq.w lbC000F88 + neg.b d1 + ext.w d1 + move.w d1,($28,a0) + addq.b #1,d0 +lbC000A7C: move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC000A8A: andi.w #$FF,d1 + move.w d1,($30,a0) + addq.b #1,d0 + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC000AA2: cmpi.b #$FF,d0 + beq.w lbC001162 + move.b ($290,a0),d3 + move.b d0,($290,a0) + move.b ($291,a0),d1 + addq.b #1,d1 + andi.b #$1F,d1 + move.b d1,($291,a0) + move.b d1,d2 + ext.w d2 + movea.w d2,a2 + move.l a2,d2 + lsl.l #4,d2 + lea (a0,d2.l),a2 + lea ($2F8,a2),a3 + move.l ($6C,a0),(a3)+ + move.l ($70,a0),(a3)+ + move.l ($74,a0),(a3)+ + move.l ($78,a0),(a3) + move.b ($16,a0),d2 + ext.w d2 + lea ($302,a2),a3 + clr.w d4 + move.b (a3),d4 + mulu.w d4,d2 + lsr.l #4,d2 + move.b d2,(a3) + tst.b d3 + bne.b lbC000B00 + move.b #1,($303,a2) +lbC000B00: sub.b d0,d1 + bmi.w lbC0018A4 + move.b d1,d0 + ext.w d0 + ext.l d0 + moveq #7,d4 + and.l d4,d1 + lea (lbB003E44,pc),a2 + move.b (a2,d1.l),d1 + ext.w d1 +lbC000B1A: lsl.l #4,d0 + lea (a0,d0.l),a2 + lea ($2E8,a0),a3 + lea ($2F8,a2),a5 + move.l (a5)+,(a3)+ + move.l (a5)+,(a3)+ + move.l (a5)+,(a3)+ + move.l (a5),(a3) + clr.b ($302,a2) + move.w ($2F0,a0),d2 + move.w d1,d0 + muls.w d2,d0 + moveq #12,d6 + asr.l d6,d0 + add.w d0,d2 + move.w d2,($2F0,a0) + moveq #2,d7 + cmp.l ($28,sp),d7 + beq.w lbC00063E + lea ($4F8,a0),a0 + addq.l #2,($28,sp) + movea.l ($38,a0),a2 + move.w ($2A,a0),d0 + move.w ($18,a0),d1 + cmpa.w #0,a2 + bne.w lbC000234 +lbC000B6C: movea.l ($3C,a0),a3 + moveq #0,d3 + move.b (4,a3),d3 + lsl.l #8,d3 + or.b (5,a3),d3 + move.b (12,a0),d2 + beq.w lbC0003AC +lbC000B84: movea.l ($9F6,a1),a2 + moveq #0,d4 + move.b d2,d4 + addi.l #$1FFFFFFF,d4 + lsl.l #3,d4 + movea.l ($98,a2),a2 + adda.l d4,a2 + move.w d1,($1E,a0) + move.l a2,($38,a0) + andi.w #$FF,d2 + move.w d2,($1A,a0) + clr.l ($40,a0) + clr.l ($5A,a0) + move.b #1,($5E,a0) + moveq #0,d4 + move.b (3,a2),d4 + move.l d4,($4A,a0) + moveq #0,d2 + move.b (4,a2),d2 + move.l d2,($4E,a0) + move.b (5,a2),d2 + move.l d2,($52,a0) + move.b (6,a2),d2 + move.l d2,($56,a0) + clr.w ($60,a0) + move.b (a2),d2 + lea (lbB003C0C,pc),a5 + move.b (a5,d2.l),d2 + andi.w #$FF,d2 + addq.w #1,d2 + move.w d2,($66,a0) + moveq #0,d2 + move.b (1,a2),d2 + lea (lbB003BFC,pc),a5 + move.b (a5,d2.l),d2 + andi.w #$FF,d2 + move.w d2,($62,a0) + moveq #0,d2 + move.b (2,a2),d2 + lea (lbB003BEC,pc),a2 + move.b (a2,d2.l),d2 + andi.w #$FF,d2 + move.w d2,($64,a0) + clr.b (12,a0) + moveq #0,d2 +lbC000C26: add.l d4,d4 + lea (lbW003D4C,pc),a2 + move.w (a2,d4.l),d4 + andi.l #$FFFF,d4 + add.l d4,d2 + cmpi.l #$3FF,d2 + bgt.w lbC000FAE + move.l d2,($5A,a0) + lsr.w #4,d2 + bra.w lbC00041A + +lbC000C4C: add.l d2,d1 + move.l d1,($34,a0) + move.w #$FFFF,($24,a0) + move.w d1,d4 + tst.l d2 + bne.w lbC0004CC + subq.w #1,d5 + move.w d5,($32,a0) +lbC000C66: move.w d3,($70,a0) + move.w d4,($72,a0) + moveq #0,d1 + move.w ($1C,a0),d1 + addi.l #$27F,d1 + add.l d1,d1 + add.l d1,d1 + move.l (a1,d1.l),($6C,a0) + bra.w lbC0004EA + +lbC000C88: moveq #-1,d2 + cmp.l d4,d2 + beq.w lbC000D78 + moveq #1,d2 + bra.w lbC0002EE + +lbC000C96: lea ($27C,a0),a0 + addq.l #1,($28,sp) + moveq #4,d0 + cmp.l ($28,sp),d0 + bne.w lbC000220 + tst.b ($77,a1) + beq.w lbC000646 +lbC000CB0: move.w #1,($DFF096) + move.l ($6C,a1),($DFF0A0) + move.w ($70,a1),d0 + lsr.w #1,d0 + move.w d0,($DFF0A4) + move.w #0,($DFF0A8) + clr.b ($77,a1) + move.w ($74,a1),($DFF0A6) + tst.b ($2F3,a1) + beq.w lbC000662 +lbC000CE8: move.w #2,($DFF096) + move.l ($2E8,a1),($DFF0B0) + move.w ($2EC,a1),d0 + lsr.w #1,d0 + move.w d0,($DFF0B4) + move.w #0,($DFF0B8) + clr.b ($2F3,a1) + move.w ($2F0,a1),($DFF0B6) + tst.b ($56F,a1) + beq.w lbC00067E +lbC000D20: move.w #4,($DFF096) + move.l ($564,a1),($DFF0C0) + move.w ($568,a1),d0 + lsr.w #1,d0 + move.w d0,($DFF0C4) + move.w #0,($DFF0C8) + clr.b ($56F,a1) + move.w ($56C,a1),($DFF0C6) + tst.b ($7EB,a1) + bne.w lbC00069A +lbC000D58: clr.w d0 + move.b ($7EA,a1),d0 + move.w d0,($DFF0D8) + move.w ($7E8,a1),($DFF0D6) + moveq #4,d2 + move.l #$FFFFFF,d1 + bra.w lbC0006D2 + +lbC000D78: move.l a3,d4 + moveq #1,d2 + bra.w lbC0002EE + +lbC000D80: tst.w d0 + bge.w lbC0005F0 + clr.w d0 + movea.w d0,a2 + bra.w lbC0005F2 + +lbC000D8E: tst.b d1 + beq.w lbC0004EA + tst.b (6,a3) + beq.w lbC0004EA + moveq #0,d2 + move.w ($1C,a0),d2 + andi.w #$FF,d1 + lsl.w #7,d1 + move.b #1,($77,a0) + addi.l #$27F,d2 + add.l d2,d2 + add.l d2,d2 + moveq #0,d3 + move.w d1,d3 + move.l (a1,d2.l),d2 + add.l d3,d2 + move.l d2,($6C,a0) + moveq #0,d2 + move.b (10,a3),d2 + lsl.l #8,d2 + or.b (11,a3),d2 + move.l d2,d4 + subq.l #1,d4 + cmp.l d3,d4 + ble.w lbC00112E + sub.w d1,d2 + move.w d2,($70,a0) + move.w #$FFFF,($72,a0) + clr.b (13,a0) +lbC000DEC: tst.b ($26,a0) + beq.w lbC0004F2 +lbC000DF4: addi.w #$10,d0 + move.w ($2E,a0),d1 + addi.w #$FFE0,d1 + add.w d1,d0 + move.w ($66,a0),d1 + beq.w lbC000510 +lbC000E0A: subq.w #1,d1 + move.w d1,($66,a0) + bne.w lbC000552 + move.w ($62,a0),d4 + move.w ($64,a0),d1 + move.w d4,d2 + muls.w d1,d2 + asr.w #4,d2 + move.w d2,($64,a0) + bra.w lbC000518 + +lbC000E2A: move.w #$240,($2A,a0) + add.w ($28,a0),d1 + bpl.w lbC000250 +lbC000E38: clr.w ($18,a0) + clr.w d1 + bra.w lbC000260 + +lbC000E42: lsr.w #4,d2 + bra.w lbC00041A + +lbC000E48: move.w ($32,a0),d1 + cmpi.w #1,d1 + bls.w lbC00110C + subq.w #1,d1 + move.w d1,($32,a0) + move.w ($36,a0),d4 + move.w d3,($70,a0) + move.w d4,($72,a0) + moveq #0,d1 + move.w ($1C,a0),d1 + addi.l #$27F,d1 + add.l d1,d1 + add.l d1,d1 + move.l (a1,d1.l),($6C,a0) + bra.w lbC0004EA + +lbC000E80: move.b ($44,a0),d4 + cmpi.b #$8E,d4 + bhi.w lbC000FA6 + move.b d4,d5 + addq.b #1,d5 + andi.l #$FF,d4 + add.l d4,d4 + lea (lbW003C1C,pc),a2 + move.w (a2,d4.l),d4 + andi.l #$FFFF,d4 +lbC000EA6: move.b d5,($44,a0) + sub.l d4,d2 + move.l d2,d4 + move.l d2,($5A,a0) + move.l ($52,a0),d2 + lsl.l #6,d2 + movea.w d2,a2 + cmpa.l d4,a2 + bge.w lbC000F96 + move.w d4,d2 + lsr.w #4,d2 + bra.w lbC00041A + +lbC000EC8: move.b ($68,a0),d0 + moveq #0,d5 + move.b (7,a2),d5 + clr.b d7 + clr.b d3 + moveq #-1,d4 + movea.l ($38,sp),a5 + bra.w lbC0002A4 + +lbC000EE0: clr.w ($1C,a0) + movea.l ($9F6,a1),a2 + movea.l ($9C,a2),a3 + adda.l ($40,sp),a3 + move.l a3,($3C,a0) + moveq #0,d3 + move.b (4,a3),d3 + lsl.l #8,d3 + or.b (5,a3),d3 + tst.w d3 + bne.w lbC0010D6 + moveq #0,d5 + move.b (12,a3),d5 + lsl.l #8,d5 + or.b (13,a3),d5 + moveq #0,d4 + move.w d5,d4 + move.b #1,($77,a0) + move.l ($9FC,a1),d6 + add.l d4,d6 + move.l d6,($6C,a0) + moveq #0,d0 + move.b (10,a3),d0 + lsl.l #8,d0 + or.b (11,a3),d0 + move.l d0,d6 + subq.l #1,d6 + cmp.l d4,d6 + ble.w lbC00118E + sub.w d5,d0 + move.w d0,($70,a0) + move.w #$FFFF,($72,a0) +lbC000F48: clr.w d0 + move.b (7,a3),d0 + addq.w #1,d0 + move.w d0,($32,a0) + move.l d4,($34,a0) + move.w #1,($24,a0) + bra.w lbC000394 + +lbC000F62: st ($69,a0) + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC000F74: move.w #$40,($18,a0) + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC000F88: lsr.b #4,d1 + ext.w d1 + move.w d1,($28,a0) + addq.b #1,d0 + bra.w lbC000A7C + +lbC000F96: move.l d2,($5A,a0) + moveq #2,d5 + move.l d5,($40,a0) + lsr.w #4,d2 + bra.w lbC00041A + +lbC000FA6: moveq #2,d4 + moveq #-$71,d5 + bra.w lbC000EA6 + +lbC000FAE: move.l #$400,($5A,a0) + moveq #1,d6 + move.l d6,($40,a0) + move.l ($4E,a0),d2 + movea.l ($3C,sp),a2 + move.b (a2,d2.l),($44,a0) + moveq #15,d2 + cmp.l ($52,a0),d2 + beq.w lbC001182 + moveq #$40,d2 + bra.w lbC00041A + +lbC000FDA: move.l ($5A,a0),d1 + asr.l #6,d1 + move.l d1,d3 + andi.l #$FFFF,d3 + moveq #$10,d6 + sub.l d3,d6 + move.l d6,d3 + asr.l #1,d3 + move.l ($56,a0),d6 + movea.l ($3C,sp),a2 + move.b (a2,d6.l),d6 + add.b d3,d6 + move.b d6,($44,a0) + move.w d1,($48,a0) + move.w #$10,($46,a0) + moveq #3,d1 + move.l d1,($40,a0) + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC001020: clr.w ($20,a0) + move.b d0,($68,a0) + tst.b d2 + bne.w lbC00035C + bra.w lbC00036E + +lbC001032: andi.b #3,d1 + beq.b lbC001020 + andi.l #$FF,d1 + move.b (-1,a0,d1.l),d1 + bne.w lbC000826 + move.b d0,($68,a0) + moveq #1,d7 + move.b d2,d3 + bra.w lbC000360 + +lbC001052: tst.b d6 + beq.w lbC0005D8 + moveq #0,d7 + move.w ($1C,a0),d7 + addi.l #$27F,d7 + add.l d7,d7 + add.l d7,d7 + movea.l (a1,d7.l),a3 + move.l ($6C,a0),d7 + sub.l a3,d7 + move.l d7,($2C,sp) + movea.w d3,a2 + adda.w d7,a2 + moveq #0,d7 + move.b d1,d7 + movea.w d4,a5 + suba.w a2,a5 + cmp.w a5,d3 + bcc.w lbC001636 + move.w #2,($70,a0) + moveq #2,d3 + move.l ($2C,sp),d4 + lsr.l d7,d4 + add.l a3,d4 + move.l d4,($6C,a0) + bra.w lbC0005C0 + +lbC0010A0: sub.l d2,d1 + moveq #0,d2 + move.b (a3),d2 + lsl.l #8,d2 + or.b (1,a3),d2 + move.w d2,d4 + andi.l #$FFFF,d2 + move.l d2,d6 + sub.l d1,d6 + bmi.w lbC0004C6 + move.l d2,($34,a0) + move.w #1,($24,a0) + tst.l d6 + bne.w lbC0004CC + subq.w #1,d5 + move.w d5,($32,a0) + bra.w lbC000C66 + +lbC0010D6: clr.w ($72,a0) + move.b #1,($77,a0) + move.l ($9FC,a1),($6C,a0) + moveq #0,d4 + move.b (12,a3),d4 + lsl.l #8,d4 + or.b (13,a3),d4 + clr.w d0 + move.b (7,a3),d0 + addq.w #1,d0 + move.w d0,($32,a0) + move.l d4,($34,a0) + move.w #1,($24,a0) + bra.w lbC000394 + +lbC00110C: move.w ($24,a0),d4 + moveq #0,d1 + move.b (8,a3),d1 + lsl.l #8,d1 + move.l d1,d2 + or.b (9,a3),d2 + move.l ($34,a0),d1 + bra.w lbC00048A + +lbC001126: move.w d1,($18,a0) + bra.w lbC000260 + +lbC00112E: moveq #2,d2 + move.w d2,($70,a0) + move.w #$FFFF,($72,a0) + clr.b (13,a0) + bra.w lbC000DEC + +lbC001142: moveq #2,d5 + moveq #-$71,d6 + move.b d6,($44,a0) + sub.l d5,d2 + bpl.w lbC00040C +lbC001150: clr.l ($5A,a0) + clr.w d2 + addi.w #$FFF0,d4 + move.w d4,($46,a0) + bra.w lbC00041A + +lbC001162: clr.b ($14,a0) + clr.b ($282,a0) + move.w #$FF,($290,a0) + clr.w d1 + moveq #$1F,d0 + bra.w lbC000B1A + +lbC001178: add.l d2,d1 + move.l d1,($34,a0) + bra.w lbC00048A + +lbC001182: moveq #$10,d4 + move.l d4,($52,a0) + moveq #$40,d2 + bra.w lbC00041A + +lbC00118E: moveq #2,d0 + move.w d0,($70,a0) + move.w #$FFFF,($72,a0) + bra.w lbC000F48 + +lbC00119E: move.b d1,($68,a0) + clr.b d2 + add.b ($69,a0),d2 + move.b d2,($6A,a0) + move.w ($18,a0),d1 + bra.w lbC00037A + +lbC0011B4: clr.w ($72,a0) + move.b #1,($77,a0) + andi.l #$FF,d3 + addi.l #$27F,d3 + add.l d3,d3 + add.l d3,d3 + move.l (a1,d3.l),($6C,a0) + moveq #0,d3 + move.b (10,a2),d3 + lsl.l #8,d3 + or.b (11,a2),d3 + bra.w lbC000948 + +lbC0011E4: clr.w ($72,a0) + move.b #1,($77,a0) + andi.l #$FF,d1 + addi.l #$27F,d1 + add.l d1,d1 + add.l d1,d1 + move.l (a1,d1.l),($6C,a0) + moveq #0,d6 + move.b (12,a2),d6 + lsl.l #8,d6 + or.b (13,a2),d6 + clr.w d1 + move.b (7,a2),d1 + addq.w #1,d1 + move.w d1,($32,a0) + move.l d6,($34,a0) + move.w #1,($24,a0) + move.w d3,($2C,sp) + bra.w lbC000A5A + +lbC00122E: movea.l ($9F6,a1),a6 + movea.l a1,a2 + moveq #0,d0 + lea (lbB003D3C,pc),a3 + move.l a3,d7 + lea (lbW004484,pc),a3 + move.l a3,($28,sp) + lea (lbW00147C,pc),a3 + move.l a3,($2C,sp) + lea (lbB003BFC,pc),a3 + move.l a3,($30,sp) + lea (lbB003BEC,pc),a3 + move.l a3,($34,sp) + lea ($774,a1),a3 + move.l a3,($38,sp) + move.l a1,($40,sp) + movea.l d7,a5 +lbC00126A: move.l a2,d1 + addi.l #$27C,d1 + move.b (8,a2),d2 + ble.b lbC001282 + subq.b #1,d2 + move.b d2,(8,a2) + beq.w lbC00149C +lbC001282: move.b (9,a2),d2 + beq.w lbC0014D8 +lbC00128A: move.b (10,a2),d3 + bne.w lbC0016E2 + clr.w ($12,a2) + move.b #$40,(6,a2) + clr.w ($10,a2) + st ($15,a2) + clr.b (9,a2) + clr.w (10,a2) + clr.w (12,a2) + move.w #$40,($1E,a2) + move.w #$40,($18,a2) + move.w #$FF,($1C,a2) + clr.w ($20,a2) + move.w #$FFFF,($22,a2) + clr.b ($26,a2) + clr.w ($28,a2) + clr.w ($2E,a2) + clr.w ($30,a2) + move.w #$10,($2A,a2) + clr.b ($68,a2) + clr.b ($6A,a2) + move.b #1,($69,a2) + movea.l ($9F6,a1),a3 + moveq #0,d3 + move.b d2,d3 + addi.l #$1FFFFFFF,d3 + lsl.l #3,d3 + add.l ($98,a3),d3 + move.l d3,($38,a2) + clr.w d3 + move.b d2,d3 + move.w d3,($1A,a2) + move.b d2,(12,a2) +lbC001314: move.b (15,a2),d4 + blt.w lbC00152C +lbC00131C: tst.b d4 + beq.b lbC00132C + subq.b #1,d4 + bne.w lbC0016F4 + st (15,a2) + st d4 +lbC00132C: moveq #0,d2 + not.b d2 + and.l ($88,a6),d2 + add.l d2,d2 + add.l d2,d2 + add.l d0,d2 + add.l d2,d2 + movea.l ($94,a6),a3 + adda.l d2,a3 + cmpa.w #0,a3 + beq.w lbC00152C + move.b ($9F0,a1),d2 + cmp.b (1,a6),d2 + bcc.w lbC00152C + move.b (a3),d5 + moveq #0,d3 + move.b d5,d3 + beq.w lbC00152C + moveq #$27,d6 + add.l d6,d3 + add.l d3,d3 + add.l d3,d3 + andi.l #$FF,d2 + add.l d2,d2 + movea.l ($28,sp),a0 + moveq #0,d5 + move.w (a0,d2.l),d5 + add.l (a6,d3.l),d5 + beq.w lbC00152C + movea.l d5,a0 + move.b (1,a0),d2 + andi.b #15,d2 + cmpi.b #14,d2 + bne.b lbC0013B4 + tst.b d4 + bne.b lbC0013B4 + move.b (2,a0),d3 + lsr.b #4,d3 + move.b (2,a0),d2 + andi.b #15,d2 + cmpi.b #13,d3 + beq.w lbC001B6C + cmpi.b #10,d3 + beq.w lbC001A26 +lbC0013B4: st (15,a2) + move.b (1,a3),d2 + ext.w d2 + movea.w d2,a3 + movea.l d5,a0 + move.b (a0),d3 + move.b (1,a0),d2 + move.b d3,d4 + lsr.b #7,d4 + lsl.b #4,d4 + move.b d2,d6 + lsr.b #4,d6 + add.b d6,d4 + move.b d3,d7 + andi.b #$3F,d7 + tst.b d4 + beq.b lbC00140C +lbC0013DE: tst.b d7 + bne.b lbC00140C + moveq #0,d2 + move.b d4,d2 + addi.l #$1FFFFFFF,d2 + lsl.l #3,d2 + movea.l ($9F6,a1),a0 + add.l ($98,a0),d2 + move.b ($1F,a2),(6,a2) + cmp.l ($38,a2),d2 + beq.w lbC001A5A + movea.l d5,a0 + move.b (a0),d3 + move.b (1,a0),d2 +lbC00140C: andi.b #$40,d3 + andi.b #15,d2 + movea.l d5,a0 + move.b (2,a0),d5 + tst.b d3 + beq.w lbC00176A + move.b d2,d3 + or.b d5,d3 + bne.w lbC0018C0 + clr.b d5 + moveq #1,d6 + st d2 +lbC00142E: cmpi.b #$3D,d7 + beq.w lbC0018E2 +lbC001436: tst.b d4 + beq.w lbC00191A + tst.b d7 + bne.w lbC0017AE +lbC001442: tst.b d3 + beq.b lbC001452 + move.b d3,(9,a2) + move.b d5,d3 + lsr.b #4,d3 + move.b d3,(10,a2) +lbC001452: clr.b (11,a2) + clr.w ($12,a2) + tst.b d6 + bne.w lbC00152C + cmpi.b #15,d2 + bhi.w lbC00152C + andi.l #$FF,d2 + add.l d2,d2 + movea.l ($2C,sp),a0 + move.w (a0,d2.l),d2 + jmp (lbW00147C,pc,d2.w) + +lbW00147C: dc.w lbC00152C-lbW00147C,lbC001A74-lbW00147C + dc.w lbC001B56-lbW00147C,lbC00152C-lbW00147C + dc.w lbC001B16-lbW00147C,lbC001678-lbW00147C + dc.w lbC00152C-lbW00147C,lbC00152C-lbW00147C + dc.w lbC00152C-lbW00147C,lbC001B06-lbW00147C + dc.w lbC001ABC-lbW00147C,lbC001AAC-lbW00147C + dc.w lbC001A98-lbW00147C,lbC001A88-lbW00147C + dc.w lbC00152C-lbW00147C,lbC001AE0-lbW00147C +lbC00149C: move.l ($5A,a2),d3 + asr.l #6,d3 + move.l d3,d2 + andi.l #$FFFF,d2 + moveq #$10,d4 + sub.l d2,d4 + move.l d4,d2 + asr.l #1,d2 + move.l ($56,a2),d4 + move.b (a5,d4.l),d4 + add.b d2,d4 + move.b d4,($44,a2) + move.w d3,($48,a2) + move.w #$10,($46,a2) + moveq #3,d5 + move.l d5,($40,a2) + move.b (9,a2),d2 + bne.w lbC00128A +lbC0014D8: move.w ($10,a2),d3 + beq.w lbC0016DA + move.w ($2C,a2),d2 + moveq #0,d4 + move.w d3,d4 + clr.w d5 + move.b (7,a2),d5 + movea.w d2,a3 + cmp.l a3,d4 + ble.w lbC0016BC + add.w d5,d2 + move.w d2,($2C,a2) + move.b (11,a2),d5 + movea.w d2,a3 + cmpa.l d4,a3 + bgt.w lbC0016CE +lbC001508: tst.b d5 + beq.w lbC001314 + add.b (6,a2),d5 + bmi.w lbC0016EC + cmpi.b #$40,d5 + ble.w lbC001956 + move.b #$40,(6,a2) + move.b (15,a2),d4 + bge.w lbC00131C +lbC00152C: move.b ($14,a2),d2 +lbC001530: tst.b d2 + bne.w lbC0016A8 +lbC001536: movea.l d1,a2 + addq.l #1,d0 + moveq #3,d1 + cmp.l d0,d1 + bge.w lbC00126A +lbC001542: movea.l ($40,sp),a0 + move.b ($9F4,a1),d0 + subq.b #1,d0 + move.b d0,($9F4,a1) + bne.w lbC0001F6 + clr.b (15,a1) + clr.b ($28B,a1) + clr.b ($507,a1) + clr.b ($783,a1) + move.b ($9F1,a1),d0 + move.b (1,a6),d2 + moveq #0,d1 + move.b d2,d1 + subq.l #1,d1 + tst.b d0 + blt.w lbC00195E + move.b d0,d3 + ext.w d3 + movea.w d3,a2 + cmp.l a2,d1 + ble.w lbC0019D4 + move.b d0,($9F0,a1) + moveq #0,d3 + not.b d3 + and.l ($88,a6),d3 + addq.l #1,d3 + move.l d3,($88,a6) + cmp.l ($8C,a6),d3 + blt.b lbC0015A2 +lbC00159C: move.l ($90,a6),($88,a6) +lbC0015A2: st ($9F1,a1) + move.b ($9F2,a1),d3 + blt.w lbC001A0A +lbC0015AE: clr.b ($9F0,a1) + move.b ($1C6C,a1),d0 + bne.w lbC00187E + ext.w d3 + movea.w d3,a2 + move.l a2,($88,a6) + cmpa.l ($8C,a6),a2 + blt.w lbC00187E + move.l ($90,a6),($88,a6) + st ($9F2,a1) + cmpi.b #1,d2 + bhi.b lbC0015F8 + clr.b ($9F0,a1) +lbC0015DE: moveq #0,d0 + not.b d0 + and.l ($88,a6),d0 + addq.l #1,d0 + move.l d0,($88,a6) + cmp.l ($8C,a6),d0 + blt.b lbC0015F8 + move.l ($90,a6),($88,a6) +lbC0015F8: move.b ($9F3,a1),d1 + cmpi.b #$2F,d1 + bhi.w lbC001A00 +lbC001604: move.b d1,($9F4,a1) +lbC001608: clr.l ($28,sp) + lea (lbW004000,pc),a2 + move.l a2,($34,sp) + clr.w d0 + moveq #$2A,d1 + mulu.w d1,d0 + move.l d0,($40,sp) + lea (lbW004484,pc),a2 + move.l a2,($38,sp) + lea (lbW000328,pc),a6 + lea (lbB003D3C,pc),a3 + move.l a3,($3C,sp) + bra.w lbC000220 + +lbC001636: add.w a2,d3 + sub.w d4,d3 + moveq #0,d4 + move.w d3,d4 + asr.l d7,d4 + move.w d4,d3 + move.w d4,($70,a0) + move.l ($2C,sp),d4 + lsr.l d7,d4 + add.l a3,d4 + move.l d4,($6C,a0) + bra.w lbC0005C0 + +lbC001656: sub.w d7,d1 + move.w d1,($70,a0) + move.w #$FFFF,($72,a0) + bra.w lbC000A40 + +lbC001666: sub.w ($32,sp),d6 + move.w d6,($70,a0) + move.w #$FFFF,($72,a0) + bra.w lbC000948 + +lbC001678: cmpa.l ($38,sp),a2 + beq.w lbC00152C + lea ($302,a2),a3 + move.l a2,d2 + addi.l #$502,d2 + movea.l ($40,sp),a0 +lbC001690: clr.b (a3) + lea ($10,a3),a3 + cmp.l a3,d2 + bne.b lbC001690 + move.l a0,($40,sp) + tst.b d5 + bne.w lbC001C4E + st ($14,a2) +lbC0016A8: lea ($4F8,a2),a2 + addq.l #1,d0 + addq.l #1,d0 + moveq #3,d1 + cmp.l d0,d1 + bge.w lbC00126A + bra.w lbC001542 + +lbC0016BC: sub.w d5,d2 + move.w d2,($2C,a2) + move.b (11,a2),d5 + movea.w d2,a3 + cmpa.l d4,a3 + bge.w lbC001508 +lbC0016CE: move.w d3,($2C,a2) + clr.w ($10,a2) + bra.w lbC001508 + +lbC0016DA: move.b (11,a2),d5 + bra.w lbC001508 + +lbC0016E2: subq.b #1,d3 + move.b d3,(10,a2) + bra.w lbC0014D8 + +lbC0016EC: clr.b (6,a2) + bra.w lbC001314 + +lbC0016F4: move.b d4,(15,a2) + movea.l d1,a2 + addq.l #1,d0 + moveq #3,d1 + cmp.l d0,d1 + bge.w lbC00126A + bra.w lbC001542 + +lbC001708: move.l ($A5C,a1),($DFF0D0) + move.w #1,($DFF0D4) + clr.w d0 + move.b ($7EA,a1),d0 + move.w d0,($DFF0D8) + movem.l (sp)+,d2-d7/a2/a3/a5/a6 + lea ($24,sp),sp + rts + +lbC00172E: move.l ($A5C,a1),($DFF0C0) + move.w #1,($DFF0C4) + bra.w lbC0007BA + +lbC001742: move.l ($A5C,a1),($DFF0B0) + move.w #1,($DFF0B4) + bra.w lbC00078A + +lbC001756: move.l ($A5C,a1),($DFF0A0) + move.w #1,($DFF0A4) + bra.w lbC00075A + +lbC00176A: tst.b d2 + bne.w lbC001950 + tst.b d5 + beq.w lbC0019F6 + move.b d5,d6 + andi.b #15,d6 + tst.b d7 + bne.w lbC00194C + move.l a3,d2 + addq.l #1,d2 + lsl.l #4,d2 + movea.l d2,a3 + move.w d2,($3C,sp) + tst.b d6 + bne.w lbC001B98 + clr.l (a2) + move.b d7,d2 + move.b d4,d3 +lbC00179A: move.w #$10,($2A,a2) + move.w ($3C,sp),($2C,a2) + clr.w ($10,a2) + bra.w lbC001442 + +lbC0017AE: andi.l #$FF,d7 + add.l a3,d7 + lsl.l #4,d7 + movea.l d7,a3 + move.w d7,($3C,sp) + cmpi.b #3,d2 + beq.w lbC001936 + clr.w ($12,a2) + move.b #$40,(6,a2) + clr.w ($10,a2) + st ($15,a2) + clr.b (9,a2) + clr.w (10,a2) + clr.w (12,a2) + move.w #$40,($1E,a2) + move.w #$40,($18,a2) + move.w #$FF,($1C,a2) + clr.w ($20,a2) + move.w #$FFFF,($22,a2) + clr.b ($26,a2) + clr.w ($28,a2) + clr.w ($2C,a2) + clr.w ($2E,a2) + clr.w ($30,a2) + move.w #$10,($2A,a2) + clr.b ($68,a2) + clr.b ($6A,a2) + move.b #1,($69,a2) + moveq #0,d7 + move.b d4,d7 + addi.l #$1FFFFFFF,d7 + lsl.l #3,d7 + movea.l ($9F6,a1),a0 + add.l ($98,a0),d7 + move.l d7,($38,a2) + clr.w d7 + move.b d4,d7 + move.w d7,($1A,a2) + move.b d4,(12,a2) +lbC00184C: tst.b d6 + beq.w lbC00193C +lbC001852: cmpi.b #3,d2 + bne.w lbC00179A +lbC00185A: lea ($10,a3),a3 + move.w a3,($10,a2) + move.w ($2A,a2),d2 + add.w d2,($2C,a2) + clr.w ($2A,a2) + tst.b d5 + beq.w lbC001B92 + move.b d5,(7,a2) + moveq #3,d2 + bra.w lbC001442 + +lbC00187E: st ($9F2,a1) + cmpi.b #1,d2 + bhi.w lbC0015F8 + clr.b ($9F0,a1) + tst.b d0 + beq.w lbC0015DE +lbC001894: move.b ($9F3,a1),d1 + cmpi.b #$2F,d1 + bls.w lbC001604 + bra.w lbC001A00 + +lbC0018A4: addi.b #$20,d1 + move.b d1,d0 + ext.w d0 + ext.l d0 + moveq #7,d5 + and.l d5,d1 + lea (lbB003E44,pc),a2 + move.b (a2,d1.l),d1 + ext.w d1 + bra.w lbC000B1A + +lbC0018C0: move.b d2,(a2) + move.b d5,d2 + lsr.b #4,d2 + move.b d2,(1,a2) + move.b d5,d2 + andi.b #15,d2 + move.b d2,(2,a2) + moveq #1,d6 + st d2 + clr.b d3 + cmpi.b #$3D,d7 + bne.w lbC001436 +lbC0018E2: move.l ($5A,a2),d4 + asr.l #6,d4 + move.l d4,d7 + andi.l #$FFFF,d7 + movea.w #$10,a3 + suba.l d7,a3 + move.l a3,d7 + asr.l #1,d7 + movea.l ($56,a2),a3 + add.b (a5,a3.l),d7 + move.b d7,($44,a2) + move.w d4,($48,a2) + move.w #$10,($46,a2) + moveq #3,d4 + move.l d4,($40,a2) + bra.w lbC001442 + +lbC00191A: tst.b d7 + beq.w lbC001442 + moveq #0,d4 + move.b d7,d4 + add.l a3,d4 + lsl.l #4,d4 + movea.l d4,a3 + move.w d4,($3C,sp) + tst.b d6 + bne.w lbC001852 + bra.b lbC00193C + +lbC001936: tst.b d6 + bne.w lbC00185A +lbC00193C: clr.l (a2) + clr.b d6 + cmpi.b #3,d2 + bne.w lbC00179A + bra.w lbC00185A + +lbC00194C: move.b d4,d3 + move.b d6,d4 +lbC001950: clr.b d6 + bra.w lbC00142E + +lbC001956: move.b d5,(6,a2) + bra.w lbC001314 + +lbC00195E: move.b ($9F2,a1),d3 + bge.w lbC0015AE + move.b ($9F0,a1),d0 + moveq #0,d2 + move.b d0,d2 + cmp.l d1,d2 + bge.w lbC001A14 + addq.l #1,d2 + movea.l ($9F6,a1),a2 + moveq #0,d1 + move.b (1,a2),d1 + cmp.l d2,d1 + ble.w lbC001B88 + addq.b #1,d0 + move.b d0,($9F0,a1) +lbC00198C: move.b ($9F3,a1),d1 + cmpi.b #$2F,d1 + bls.w lbC001604 + btst #0,d0 + beq.b lbC001A00 + andi.b #15,d1 + move.b d1,($9F4,a1) + clr.l ($28,sp) + lea (lbW004000,pc),a2 + move.l a2,($34,sp) + clr.w d0 + moveq #$2A,d1 + mulu.w d1,d0 + move.l d0,($40,sp) + lea (lbW004484,pc),a2 + move.l a2,($38,sp) + lea (lbW000328,pc),a6 + lea (lbB003D3C,pc),a3 + move.l a3,($3C,sp) + bra.w lbC000220 + +lbC0019D4: move.b d2,d0 + subq.b #1,d0 + move.b d0,($9F0,a1) + moveq #0,d3 + not.b d3 + and.l ($88,a6),d3 + addq.l #1,d3 + move.l d3,($88,a6) + cmp.l ($8C,a6),d3 + blt.w lbC0015A2 + bra.w lbC00159C + +lbC0019F6: clr.b d6 + move.b d5,d2 + move.b d5,d3 + bra.w lbC00142E + +lbC001A00: lsr.b #4,d1 + move.b d1,($9F4,a1) + bra.w lbC001608 + +lbC001A0A: moveq #0,d2 + move.b d0,d2 + cmp.l d2,d1 + bgt.w lbC00198C +lbC001A14: move.b ($1C6C,a1),d0 + clr.b ($9F0,a1) + tst.b d0 + bne.w lbC001894 + bra.w lbC0015DE + +lbC001A26: move.b d2,(14,a2) + st (15,a2) + move.b (1,a3),d2 + ext.w d2 + movea.w d2,a3 + movea.l d5,a0 + move.b (a0),d3 + move.b (1,a0),d2 + move.b d3,d4 + lsr.b #7,d4 + lsl.b #4,d4 + move.b d2,d6 + lsr.b #4,d6 + add.b d6,d4 + move.b d3,d7 + andi.b #$3F,d7 + tst.b d4 + beq.w lbC00140C + bra.w lbC0013DE + +lbC001A5A: clr.l ($40,a2) + clr.l ($5A,a2) + move.b #1,($5E,a2) + movea.l d5,a0 + move.b (a0),d3 + move.b (1,a0),d2 + bra.w lbC00140C + +lbC001A74: andi.w #$FF,d5 + move.w d5,($12,a2) + move.b ($14,a2),d2 + beq.w lbC001536 + bra.w lbC0016A8 + +lbC001A88: move.b d5,($9F1,a1) + move.b ($14,a2),d2 + beq.w lbC001536 + bra.w lbC0016A8 + +lbC001A98: cmpi.b #$40,d5 + bls.b lbC001AA0 + moveq #$40,d5 +lbC001AA0: move.b d5,(6,a2) + move.b ($14,a2),d2 + bra.w lbC001530 + +lbC001AAC: move.b d5,($9F2,a1) + move.b ($14,a2),d2 + beq.w lbC001536 + bra.w lbC0016A8 + +lbC001ABC: move.b ($14,a2),d2 + tst.b d5 + beq.w lbC001530 + move.b d5,d3 + andi.b #15,d3 + beq.w lbC001C82 + neg.b d5 + move.b d5,(11,a2) +lbC001AD6: tst.b d2 + beq.w lbC001536 + bra.w lbC0016A8 + +lbC001AE0: move.b d5,($9F3,a1) + cmpi.b #$2F,d5 + bhi.w lbC001C2A + move.b d5,($9F4,a1) + sne d2 + neg.b d2 + move.b d2,($9FA,a1) + move.b ($14,a2),d2 +lbC001AFC: tst.b d2 + beq.w lbC001536 + bra.w lbC0016A8 + +lbC001B06: move.b d5,(13,a2) + move.b ($14,a2),d2 + beq.w lbC001536 + bra.w lbC0016A8 + +lbC001B16: clr.w ($60,a2) + move.w #1,($66,a2) + moveq #15,d2 + and.l d5,d2 + movea.l ($30,sp),a0 + move.b (a0,d2.l),d2 + andi.w #$FF,d2 + move.w d2,($62,a2) + move.b d5,d2 + lsr.b #4,d2 + andi.l #$FF,d2 + movea.l ($34,sp),a3 + move.b (a3,d2.l),d2 + andi.w #$FF,d2 + move.w d2,($64,a2) + move.b ($14,a2),d2 + bra.w lbC001530 + +lbC001B56: andi.w #$FF,d5 + neg.w d5 + move.w d5,($12,a2) + move.b ($14,a2),d2 + beq.w lbC001536 + bra.w lbC0016A8 + +lbC001B6C: tst.b ($9F3,a1) + beq.w lbC0013B4 + move.b d2,(15,a2) + movea.l d1,a2 + addq.l #1,d0 + moveq #3,d1 + cmp.l d0,d1 + bge.w lbC00126A + bra.w lbC001542 + +lbC001B88: clr.b d0 + move.b d0,($9F0,a1) + bra.w lbC00198C + +lbC001B92: moveq #3,d2 + bra.w lbC001442 + +lbC001B98: move.b d4,d3 + move.b d7,d2 + move.b d6,d4 + clr.b d6 + clr.w ($12,a2) + move.b #$40,(6,a2) + clr.w ($10,a2) + st ($15,a2) + clr.b (9,a2) + clr.w (10,a2) + clr.w (12,a2) + move.w #$40,($1E,a2) + move.w #$40,($18,a2) + move.w #$FF,($1C,a2) + clr.w ($20,a2) + move.w #$FFFF,($22,a2) + clr.b ($26,a2) + clr.w ($28,a2) + clr.w ($2C,a2) + clr.w ($2E,a2) + clr.w ($30,a2) + move.w #$10,($2A,a2) + clr.b ($68,a2) + clr.b ($6A,a2) + move.b #1,($69,a2) + moveq #0,d7 + move.b d4,d7 + addi.l #$1FFFFFFF,d7 + lsl.l #3,d7 + movea.l ($9F6,a1),a0 + add.l ($98,a0),d7 + move.l d7,($38,a2) + clr.w d7 + move.b d4,d7 + move.w d7,($1A,a2) + move.b d4,(12,a2) + bra.w lbC00184C + +lbC001C2A: move.b d5,d2 + btst #0,($9F0,a1) + beq.b lbC001C6A + andi.b #15,d2 + move.b d2,($9F4,a1) + tst.b d5 + sne d2 + neg.b d2 + move.b d2,($9FA,a1) + move.b ($14,a2),d2 + bra.w lbC001AFC + +lbC001C4E: move.b d5,d2 + andi.b #15,d2 + add.b d2,d2 + move.b d2,($14,a2) + lsr.b #4,d5 + move.b d5,($16,a2) + tst.b d2 + beq.w lbC001536 + bra.w lbC0016A8 + +lbC001C6A: lsr.b #4,d2 + move.b d2,($9F4,a1) + tst.b d5 + sne d2 + neg.b d2 + move.b d2,($9FA,a1) + move.b ($14,a2),d2 + bra.w lbC001AFC + +lbC001C82: lsr.b #4,d5 + move.b d5,(11,a2) + bra.w lbC001AD6 + +lbC001C8C: move.l ($4A,a0),d4 + bra.w lbC000C26 + +playerTick: lea (lbL000000,pc),a1 + adda.l (20,a1),a1 + move.l a0,-(sp) + jsr (a1) + addq.l #4,sp + rts + +playerInit: move.l a3,-(sp) + move.l a2,-(sp) + lea (lbL000000,pc),a3 + adda.l (16,a3),a3 + move.l a2,-(sp) + move.l a1,-(sp) + move.l a0,-(sp) + jsr (a3) + lea (12,sp),sp + movea.l (sp)+,a2 + movea.l (sp)+,a3 + rts + +songInit: move.l a3,-(sp) + move.l a2,-(sp) + lea (lbL000000,pc),a3 + adda.l (12,a3),a3 + move.l a2,-(sp) + move.l a1,-(sp) + move.l a0,-(sp) + jsr (a3) + lea (12,sp),sp + movea.l (sp)+,a2 + movea.l (sp)+,a3 + rts + +lbC001CE0: movem.l d2-d7/a2/a3,-(sp) + move.l ($24,sp),d0 + move.l ($28,sp),d5 + movea.l ($2C,sp),a1 + move.l a1,d4 + subq.l #1,d4 + cmpa.w #0,a1 + beq.w lbC001DA8 + move.b d5,d7 + move.l d0,d1 + neg.l d1 + moveq #3,d2 + and.l d2,d1 + moveq #5,d6 + movea.l d0,a2 + cmp.l d4,d6 + bcc.b lbC001D78 + tst.l d1 + beq.b lbC001D36 + move.b d5,(a2)+ + subq.l #1,d4 + moveq #1,d2 + cmp.l d1,d2 + beq.b lbC001D36 + movea.l d0,a2 + addq.l #2,a2 + movea.l d0,a0 + move.b d5,(1,a0) + subq.l #1,d4 + moveq #3,d2 + cmp.l d1,d2 + bne.b lbC001D36 + addq.l #1,a2 + move.b d5,(2,a0) + subq.l #1,d4 +lbC001D36: move.l a1,d3 + sub.l d1,d3 + moveq #0,d6 + move.b d5,d6 + move.l d6,d2 + swap d2 + clr.w d2 + movea.l d2,a0 + move.l d6,d2 + lsl.w #8,d2 + swap d2 + clr.w d2 + lsl.l #8,d6 + movea.l d6,a3 + move.l a0,d6 + or.l d6,d2 + move.l a3,d6 + or.l d6,d2 + move.b d7,d2 + movea.l d0,a0 + adda.l d1,a0 + moveq #-4,d1 + and.l d3,d1 + add.l a0,d1 +lbC001D66: move.l d2,(a0)+ + cmpa.l d1,a0 + bne.b lbC001D66 + moveq #-4,d1 + and.l d3,d1 + adda.l d1,a2 + sub.l d1,d4 + cmp.l d3,d1 + beq.b lbC001DA8 +lbC001D78: move.b d5,(a2) + tst.l d4 + beq.b lbC001DA8 + move.b d5,(1,a2) + moveq #1,d1 + cmp.l d4,d1 + beq.b lbC001DA8 + move.b d5,(2,a2) + moveq #2,d2 + cmp.l d4,d2 + beq.b lbC001DA8 + move.b d5,(3,a2) + moveq #3,d6 + cmp.l d4,d6 + beq.b lbC001DA8 + move.b d5,(4,a2) + subq.l #4,d4 + beq.b lbC001DA8 + move.b d5,(5,a2) +lbC001DA8: movem.l (sp)+,d2-d7/a2/a3 + rts + +lbC001DAE: lea (-$78,sp),sp + movem.l d2-d7/a2/a3/a5/a6,-(sp) + movea.l ($A4,sp),a5 + pea ($1C6E).w + clr.l -(sp) + move.l a5,-(sp) + lea (lbC001CE0,pc),a0 + move.l a0,($78,sp) + jsr (a0) + move.w (lbW004002,pc),d2 + lea (12,sp),sp + beq.w lbC0027F6 +lbC001DD8: movea.l ($AC,sp),a1 + move.w (2,a1),($32,sp) + move.w ($32,sp),d0 + add.w d0,d0 + add.w ($32,sp),d0 + andi.l #$FFFF,d0 + move.l (4,a1),d1 + lea ($A0,a1),a0 + lea ($49C,a1),a1 +lbC001DFE: move.l d1,(a0)+ + add.l d0,d1 + cmpa.l a1,a0 + bne.b lbC001DFE + clr.b ($9FA,a5) + move.l ($AC,sp),($9F6,a5) + move.w #$FF,($9F0,a5) + move.w #$FF06,($9F2,a5) + clr.b ($9F4,a5) + clr.b ($1C6C,a5) + movea.l ($AC,sp),a3 + move.l ($9C,a3),d0 + move.b #$40,(6,a5) + clr.w ($10,a5) + clr.w ($12,a5) + move.w #$FF,($14,a5) + clr.b ($16,a5) + clr.w (8,a5) + clr.w (10,a5) + clr.w (12,a5) + clr.l (a5) + clr.l ($5A,a5) + moveq #3,d1 + move.l d1,($40,a5) + move.l d0,($3C,a5) + move.b #$40,($282,a5) + clr.w ($28C,a5) + clr.w ($28E,a5) + move.w #$FF,($290,a5) + clr.b ($292,a5) + clr.w ($284,a5) + clr.w ($286,a5) + clr.w ($288,a5) + clr.l ($27C,a5) + clr.l ($2D6,a5) + move.l d1,($2BC,a5) + move.l d0,($2B8,a5) + move.b #$40,($4FE,a5) + clr.w ($508,a5) + clr.w ($50A,a5) + move.w #$FF,($50C,a5) + clr.b ($50E,a5) + clr.w ($500,a5) + clr.w ($502,a5) + clr.w ($504,a5) + clr.l ($4F8,a5) + clr.l ($552,a5) + move.l d1,($538,a5) + move.l d0,($534,a5) + clr.b ($788,a5) + clr.b ($78A,a5) + clr.w ($786,a5) + move.b #$40,($77A,a5) + clr.w ($784,a5) + clr.b ($77F,a5) + clr.w ($77C,a5) + clr.b ($781,a5) + clr.b ($77E,a5) + st ($789,a5) + clr.b ($780,a5) + clr.l ($774,a5) + clr.l ($7CE,a5) + move.l d1,($7B4,a5) + move.l d0,($7B0,a5) + lea (lbW003BD4,pc),a6 + lea ($BE0,a5),a2 + moveq #0,d5 + lea (lbC003B4A,pc),a0 + move.l a0,($60,sp) + lea (lbC003AEE,pc),a1 + move.l a1,($38,sp) + move.l a5,($3C,sp) +lbC001F24: moveq #0,d0 + move.w (a6)+,d0 + move.l d0,-(sp) + move.l #$400000,-(sp) + movea.l ($68,sp),a3 + jsr (a3) + addq.l #8,sp + move.l d0,d6 + move.b d0,(a2) + move.l d0,-(sp) + move.l #$FF00,-(sp) + movea.l ($40,sp),a5 + jsr (a5) + addq.l #8,sp + move.l d6,d1 + lsr.l #1,d1 + movea.l d1,a5 + move.l d6,d4 + lsr.l #2,d4 + neg.w d4 + suba.l a3,a3 + clr.w d7 + suba.l a1,a1 + moveq #0,d3 + move.l d5,d1 + add.l d5,d1 + add.l d5,d1 + lsl.l #7,d1 + add.l d5,d1 + add.l ($3C,sp),d1 + move.w d0,($34,sp) +lbC001F72: moveq #0,d2 + move.w a1,d2 + asr.l #8,d2 + movea.l d1,a0 + adda.l d3,a0 + moveq #$7F,d0 + sub.b d2,d0 + move.b d0,($A60,a0) + add.b d2,d2 + movea.w d4,a0 + tst.w d4 + blt.w lbC0021F2 + movea.w a0,a0 + adda.l d1,a0 + cmpa.l a3,a5 + bcc.w lbC0021FE +lbC001F98: moveq #$7F,d0 + sub.b d2,d0 + move.b d0,($B60,a0) + moveq #-$80,d2 +lbC001FA2: movea.l d1,a0 + adda.l d3,a0 + move.b d2,($AE0,a0) + adda.w ($34,sp),a1 + addq.w #1,d7 + moveq #0,d3 + move.w d7,d3 + movea.l d3,a3 + addq.w #1,d4 + cmp.l d3,d6 + bhi.b lbC001F72 +lbC001FBC: addq.l #1,d5 + lea ($181,a2),a2 + moveq #12,d1 + cmp.l d5,d1 + bne.w lbC001F24 + movea.l ($3C,sp),a5 + tst.l ($A8,sp) + beq.b lbC00204A + move.l ($A8,sp),($A5C,a5) + movea.l ($A8,sp),a0 + clr.b (a0) + movea.l ($A5C,a5),a0 + clr.b (1,a0) + movea.l ($AC,sp),a1 + move.b (a1),d0 + beq.b lbC00204A + move.l ($A5C,a5),d2 + lea ($9FC,a5),a2 + movea.w #$14,a0 + adda.l ($9C,a1),a0 + andi.l #$FF,d0 + add.l d0,d0 + add.l d0,d0 + move.l a5,d1 + add.l d0,d1 + addi.l #$9FC,d1 + movea.w #2,a1 +lbC002018: lea (a1,d2.l),a3 + move.l a3,(a2)+ + moveq #0,d0 + move.b (5,a0),d0 + addq.l #1,d0 + lsl.l #7,d0 + btst #2,(a0) + beq.w lbC002230 + move.l d0,d3 + lsr.l #1,d3 + move.l d0,d4 + lsr.l #2,d4 + add.l d4,d3 + add.l d0,d3 + lsr.l #3,d0 + add.l d3,d0 + adda.l d0,a1 + lea ($2A,a0),a0 + cmp.l a2,d1 + bne.b lbC002018 +lbC00204A: move.l ($DFF004),d0 + move.l d0,($88,sp) + move.l ($88,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($88,sp) + move.l ($88,sp),d0 + cmpi.l #$C8,d0 + bne.b lbC00204A +lbC002070: move.l ($DFF004),d0 + move.l d0,($84,sp) + move.l ($84,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($84,sp) + move.l ($84,sp),d0 + cmpi.l #$C7,d0 + bne.b lbC002070 + move.w #$780,($DFF09A) + move.w #$780,($DFF09C) + move.w #$780,($DFF09C) + movea.l #$BFE001,a0 + move.b (a0),d0 + ori.b #2,d0 + move.b d0,(a0) + move.w #15,($DFF096) +lbC0020C4: move.l ($DFF004),d0 + move.l d0,($98,sp) + move.l ($98,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($98,sp) + move.l ($98,sp),d0 + cmpi.l #$C8,d0 + bne.b lbC0020C4 +lbC0020EA: move.l ($DFF004),d0 + move.l d0,($94,sp) + move.l ($94,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($94,sp) + move.l ($94,sp),d0 + cmpi.l #$C7,d0 + bne.b lbC0020EA + moveq #0,d0 + move.l d0,($DFF0A0) + move.w #2,($DFF0A4) + move.w #0,($DFF0A8) + move.w #0,($DFF0A6) + move.l d0,($DFF0B0) + move.w #2,($DFF0B4) + move.w #0,($DFF0B8) + move.w #0,($DFF0B6) + move.l d0,($DFF0C0) + move.w #2,($DFF0C4) + move.w #0,($DFF0C8) + move.w #0,($DFF0C6) + move.l d0,($DFF0D0) + move.w #2,($DFF0D4) + move.w #0,($DFF0D8) + move.w #0,($DFF0D6) + move.w #$820F,($DFF096) +lbC002192: move.l ($DFF004),d0 + move.l d0,($90,sp) + move.l ($90,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($90,sp) + move.l ($90,sp),d0 + cmpi.l #$C8,d0 + bne.b lbC002192 +lbC0021B8: move.l ($DFF004),d0 + move.l d0,($8C,sp) + move.l ($8C,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($8C,sp) + move.l ($8C,sp),d0 + cmpi.l #$C7,d0 + bne.b lbC0021B8 + movea.l ($AC,sp),a0 + tst.b (a0) + bne.w lbC002268 + movem.l (sp)+,d2-d7/a2/a3/a5/a6 + lea ($78,sp),sp + rts + +lbC0021F2: adda.w d6,a0 + movea.w a0,a0 + adda.l d1,a0 + cmpa.l a3,a5 + bcs.w lbC001F98 +lbC0021FE: addi.b #$80,d2 + move.b d2,($B60,a0) + moveq #$7F,d2 + cmpa.l a3,a5 + bne.w lbC001FA2 + moveq #-$80,d2 + movea.l d1,a0 + adda.l d3,a0 + move.b d2,($AE0,a0) + adda.w ($34,sp),a1 + addq.w #1,d7 + moveq #0,d3 + move.w d7,d3 + movea.l d3,a3 + addq.w #1,d4 + cmp.l d3,d6 + bhi.w lbC001F72 + bra.w lbC001FBC + +lbC002230: adda.l d0,a1 + lea ($2A,a0),a0 + cmp.l a2,d1 + bne.w lbC002018 + move.l ($DFF004),d0 + move.l d0,($88,sp) + move.l ($88,sp),d0 + lsr.l #8,d0 + andi.l #$1FF,d0 + move.l d0,($88,sp) + move.l ($88,sp),d0 + cmpi.l #$C8,d0 + bne.w lbC00204A + bra.w lbC002070 + +lbC002268: lea ($A60,a5),a1 + move.l a1,($78,sp) + clr.l ($64,sp) + lea ($96C,a0),a0 + move.l a0,($80,sp) + lea ($9C,sp),a3 + move.l a3,($7C,sp) + move.l a5,($3C,sp) +lbC002288: movea.l ($80,sp),a5 + move.l ($64,sp),d1 + move.b (a5,d1.l),($6B,sp) + movea.l ($3C,sp),a1 + movea.l ($9F6,a1),a0 + clr.w d0 + move.b ($6B,sp),d0 + mulu.w #$2A,d0 + movea.l ($9C,a0),a6 + adda.l d0,a6 + moveq #0,d0 + move.b ($6B,sp),d0 + addi.l #$27F,d0 + add.l d0,d0 + add.l d0,d0 + move.l (a1,d0.l),($50,sp) + moveq #0,d0 + move.b ($19,a6),d0 + addq.l #1,d0 + move.w #$80,d1 + mulu.w d0,d1 + move.l d1,($54,sp) + move.l d1,-(sp) + clr.l -(sp) + move.l ($58,sp),-(sp) + movea.l ($78,sp),a3 + jsr (a3) + move.b ($17,a6),($58,sp) + move.b ($58,sp),($A8,sp) + move.b (14,a6),d0 + add.b ($58,sp),d0 + move.b d0,($A9,sp) + move.b (15,a6),d1 + add.b ($58,sp),d1 + move.b d1,($AA,sp) + move.b ($10,a6),d2 + add.b ($58,sp),d2 + move.b d2,($AB,sp) + move.b (14,a6),d0 + or.b (15,a6),d0 + or.b ($10,a6),d0 + lea (12,sp),sp + seq d0 + neg.b d0 + move.b ($29,a6),d1 + lsr.b #3,d1 + andi.b #3,d1 + move.b d1,($6A,sp) + suba.l a5,a5 + clr.l ($58,sp) + andi.l #$FF,d0 + move.l d0,($70,sp) + move.l ($50,sp),d3 + add.l ($54,sp),d3 + move.l d3,($44,sp) + moveq #0,d0 + move.b d1,d0 + moveq #9,d4 + sub.l d0,d4 + move.l d4,($74,sp) + clr.l ($40,sp) + lea (lbC003ACC,pc),a0 + move.l a0,($38,sp) + movea.l a5,a3 +lbC00236C: lea ($9C,sp),a0 + movea.l ($40,sp),a1 + move.b (a0,a1.l),d0 + cmpa.w #0,a1 + beq.b lbC002386 + cmp.b ($4C,sp),d0 + beq.w lbC0025C0 +lbC002386: ext.w d0 + movea.w d0,a2 + moveq #11,d1 + cmp.l a2,d1 + bge.w lbC00294A + lea (-12,a2),a0 + moveq #11,d0 + cmp.l a0,d0 + bge.w lbC0030AE + lea (-$18,a2),a0 + cmp.l a0,d0 + bge.w lbC0030BA + lea (-$24,a2),a0 + cmp.l a0,d0 + bge.w lbC0030F4 + lea (-$30,a2),a0 + cmp.l a0,d0 + bge.w lbC003106 + lea (-$3C,a2),a0 + cmp.l a0,d0 + bge.w lbC00310C + lea (-$48,a2),a0 + cmp.l a0,d0 + bge.w lbC00311E + lea (-$54,a2),a0 + cmp.l a0,d0 + bge.w lbC003124 + lea (-$60,a2),a0 + cmp.l a0,d0 + bge.w lbC0032DA + lea (-$6C,a2),a0 + cmp.l a0,d0 + bge.w lbC0032EE + lea (-$78,a2),a0 + moveq #10,d1 +lbC0023F4: move.l a0,d0 + add.l a0,d0 + add.l a0,d0 + lsl.l #7,d0 + adda.l d0,a0 + adda.l ($78,sp),a0 + move.b ($14,a6),d2 + move.b d2,d0 + andi.b #3,d0 + bne.w lbC0029EC +lbC002410: movea.l a0,a3 +lbC002412: move.w d1,d0 + ext.l d0 + tst.w d1 + ble.w lbC002A02 +lbC00241C: move.l #$8000,d6 + lsl.l d0,d6 +lbC002424: move.b ($15,a6),($5C,sp) + move.b ($11,a6),($5E,sp) + moveq #0,d7 + move.b ($180,a0),d7 + move.b ($21,a6),d3 + andi.b #$10,d2 + move.b d2,($34,sp) + bne.w lbC002A36 +lbC002446: tst.b d3 + ble.w lbC00306E + move.b d3,d2 + ext.w d2 + muls.w d2,d2 +lbC002452: moveq #10,d3 + lsl.l d3,d2 + move.b ($18,a6),($69,sp) + moveq #15,d4 + lsl.l d4,d7 + moveq #15,d5 + sub.l d0,d5 + move.l d5,d0 + lsl.l #3,d0 + movea.l d0,a5 + moveq #0,d5 + move.b ($13,a6),d5 + moveq #11,d0 + lsl.l d0,d5 + moveq #0,d3 + move.b ($5C,sp),d3 + move.l d3,($48,sp) + moveq #0,d4 + move.b ($16,a6),d4 + move.l d3,d0 + moveq #14,d3 + lsl.l d3,d0 + move.l a5,-(sp) + move.l d0,-(sp) + move.l d1,($32,sp) + movea.l ($40,sp),a0 + jsr (a0) + addq.l #8,sp + move.l d0,d3 + asr.l #8,d3 + moveq #14,d0 + lsl.l d0,d4 + move.l a5,-(sp) + move.l d4,-(sp) + movea.l ($40,sp),a0 + jsr (a0) + addq.l #8,sp + asr.l #8,d0 + movea.l d0,a5 + move.l ($2A,sp),d1 + cmp.l d3,d0 + bge.w lbC002A54 + neg.l d5 + movea.l d0,a0 + movea.l d3,a5 + moveq #0,d0 + move.b ($5E,sp),d0 + move.l d6,-(sp) + move.l d0,-(sp) + move.l d1,($32,sp) + move.l a0,($36,sp) + movea.l ($40,sp),a1 + jsr (a1) + addq.l #8,sp + movea.l ($70,sp),a1 + move.l ($40,sp),d4 + pea (a1,d4.l) + move.l d0,-(sp) + movea.l ($40,sp),a1 + jsr (a1) + addq.l #8,sp + move.l d0,d4 + move.l d6,-(sp) + move.l ($4C,sp),-(sp) + movea.l ($40,sp),a1 + jsr (a1) + addq.l #8,sp + add.l d4,d0 + move.l ($2A,sp),d1 + movea.l ($2E,sp),a0 + cmp.l d7,d0 + ble.b lbC002516 +lbC002510: sub.l d7,d0 + cmp.l d7,d0 + bgt.b lbC002510 +lbC002516: cmpa.w #0,a3 + beq.w lbC002B3E + move.l d6,d1 + tst.l ($58,sp) + beq.b lbC00252E + move.l ($74,sp),d4 + asr.l d4,d1 + add.l d6,d1 +lbC00252E: tst.l ($54,sp) + beq.w lbC0025C0 + clr.w d4 + move.b ($69,sp),d4 + move.w d4,($48,sp) + movea.l ($50,sp),a1 + suba.l a2,a2 + tst.b ($34,sp) + bne.w lbC002ABA + move.l d6,($34,sp) +lbC002552: move.l d0,d4 + sub.l d3,d4 + bmi.w lbC002A4C + moveq #15,d6 + asr.l d6,d4 + move.b (a3,d4.l),d4 + ext.w d4 +lbC002564: move.w ($48,sp),d6 + muls.w d4,d6 + asr.l #7,d6 + move.b (a1),d4 + ext.w d4 + add.w d6,d4 + cmpi.w #$7F,d4 + ble.b lbC00257A + moveq #$7F,d4 +lbC00257A: addq.l #1,a1 + cmpi.w #$FF80,d4 + bge.b lbC002584 + moveq #-$80,d4 +lbC002584: move.b d4,(-1,a1) + add.l d1,d0 + cmp.l d7,d0 + blt.b lbC0025A2 + sub.l d7,d0 + add.l d5,d3 + cmp.l a5,d3 + blt.b lbC00259A + neg.l d5 + move.l a5,d3 +lbC00259A: cmp.l a0,d3 + bgt.b lbC0025A2 + neg.l d5 + move.l a0,d3 +lbC0025A2: tst.l d2 + beq.b lbC0025BA + adda.l d2,a2 + move.l a2,d1 + moveq #10,d4 + asr.l d4,d1 + add.l ($34,sp),d1 + cmp.l d7,d1 + bcs.b lbC0025BA + moveq #0,d2 + moveq #0,d1 +lbC0025BA: cmpa.l ($44,sp),a1 + bne.b lbC002552 +lbC0025C0: addq.l #1,($40,sp) + moveq #4,d0 + cmp.l ($40,sp),d0 + bne.w lbC00236C + movea.l a3,a5 + tst.b ($6A,sp) + beq.b lbC0025E6 + cmpa.w #0,a3 + beq.b lbC0025E6 + moveq #1,d1 + cmp.l ($58,sp),d1 + bne.w lbC0027DE +lbC0025E6: move.b ($1F,a6),d7 + beq.w lbC002D50 + move.b ($25,a6),d0 + ext.w d0 + ext.l d0 + lsl.l #7,d0 + move.l d0,($38,sp) + moveq #0,d0 + move.b ($22,a6),d0 + lsl.l #8,d0 + moveq #0,d1 + move.b ($23,a6),d1 + lsl.l #8,d1 + move.l d1,($44,sp) + moveq #0,d1 + move.b ($24,a6),d1 + lsl.l #8,d1 + move.l d1,($34,sp) + tst.l ($54,sp) + beq.w lbC002D50 + move.l ($44,sp),d1 + asr.l #8,d1 + not.b d1 + move.b d1,($58,sp) + andi.w #$FF,d1 + move.w d1,($5E,sp) + move.l ($34,sp),d1 + asr.l #8,d1 + not.b d1 + move.b d1,($48,sp) + clr.w d2 + move.b d1,d2 + move.w d2,($5C,sp) + movea.l ($50,sp),a2 + clr.w d4 + clr.w d6 + clr.w d5 + clr.w d3 + moveq #$40,d1 + sub.l a2,d1 + move.l d1,($4C,sp) + movea.l d0,a3 + adda.l ($38,sp),a3 + tst.l ($38,sp) + ble.w lbC002796 +lbC00266E: cmp.l ($34,sp),d0 + bgt.w lbC002D2A + cmpa.l ($34,sp),a3 + blt.w lbC002936 + move.l ($44,sp),d2 + cmp.l ($34,sp),d2 + beq.w lbC0032E0 + neg.l ($38,sp) + move.w ($5C,sp),d2 + move.b ($48,sp),d1 + movea.l ($34,sp),a3 +lbC00269A: move.b ($20,a6),d0 + movea.w d0,a1 + movea.l a2,a5 + cmpi.b #2,d7 + beq.w lbC0027D0 +lbC0026AA: cmpi.b #4,d7 + beq.w lbC0027D0 +lbC0026B2: move.w d2,d1 + movea.w d2,a0 + move.w a1,d0 + tst.b d0 + beq.b lbC0026F2 + move.l a0,d0 + lsl.l #8,d0 + movea.l d0,a0 + move.w a1,d0 + andi.w #$FF,d0 + add.w d0,d0 + movea.w #$B6,a1 + suba.w d0,a1 + move.w a1,d0 + cmpi.w #$36,d0 + bge.b lbC0026DA + moveq #$36,d0 +lbC0026DA: movea.w d0,a1 + move.l a1,-(sp) + move.l a0,-(sp) + move.l d1,($32,sp) + movea.l ($68,sp),a0 + jsr (a0) + addq.l #8,sp + movea.l d0,a0 + move.l ($2A,sp),d1 +lbC0026F2: move.w d1,d0 + add.w a0,d0 + cmpi.b #1,d7 + beq.w lbC002C6E + movea.l a2,a0 + lea ($40,a2),a1 + move.w d0,($70,sp) +lbC002708: move.w d3,d1 + sub.w d5,d1 + move.w ($70,sp),d0 + muls.w d0,d1 + move.b (a0)+,d0 + ext.w d0 + movea.w d0,a5 + asr.l #8,d1 + sub.w d3,d1 + add.w d0,d1 + move.w d2,d0 + muls.w d1,d0 + move.l d0,d1 + asr.l #8,d1 + add.w d1,d3 + move.w d3,d1 + sub.w d5,d1 + move.w d2,d0 + muls.w d1,d0 + move.l d0,d1 + asr.l #8,d1 + add.w d1,d5 + move.w d5,d1 + sub.w d6,d1 + move.w d2,d0 + muls.w d1,d0 + move.l d0,d1 + asr.l #8,d1 + add.w d1,d6 + move.w d6,d1 + sub.w d4,d1 + move.w d2,d0 + muls.w d1,d0 + move.l d0,d1 + asr.l #8,d1 + add.w d1,d4 + cmpi.b #2,d7 + beq.w lbC002944 + cmpi.b #3,d7 + beq.w lbC00290C + cmpi.b #4,d7 + beq.w lbC0028F2 + clr.b d1 +lbC00276C: move.b d1,(-1,a0) + cmpa.l a0,a1 + bne.b lbC002708 +lbC002774: adda.l ($4C,sp),a2 + cmpa.l ($54,sp),a2 + bcc.w lbC002D50 + move.b ($1F,a6),d7 + movea.l a1,a2 + move.l a3,d0 + movea.l d0,a3 + adda.l ($38,sp),a3 + tst.l ($38,sp) + bgt.w lbC00266E +lbC002796: cmp.l ($44,sp),d0 + blt.w lbC00308A + cmpa.l ($44,sp),a3 + bgt.w lbC002936 + move.l ($44,sp),d1 + movea.l d1,a3 + cmp.l ($34,sp),d1 + beq.w lbC0034F2 + neg.l ($38,sp) + move.w ($5E,sp),d2 + move.b ($58,sp),d1 + move.b ($20,a6),d0 + movea.w d0,a1 + movea.l a2,a5 + cmpi.b #2,d7 + bne.w lbC0026AA +lbC0027D0: andi.w #$FF,d1 + move.w #$FF,d2 + sub.w d1,d2 + bra.w lbC0026B2 + +lbC0027DE: moveq #1,d2 + move.l d2,($58,sp) + clr.l ($40,sp) + lea (lbC003ACC,pc),a0 + move.l a0,($38,sp) + movea.l a5,a3 + bra.w lbC00236C + +lbC0027F6: lea (lbW004002,pc),a0 + lea (lbW004482,pc),a1 + moveq #0,d3 + move.w (lbW004000,pc),d3 +lbC002804: move.l d3,d0 + swap d0 + clr.w d0 + moveq #0,d3 + move.w ($1E,a0),d3 + move.l d3,d1 + swap d1 + clr.w d1 + sub.l d0,d1 + asr.l #4,d1 + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,(a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,(2,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,(4,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,(6,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,(8,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,(10,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,(12,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,(14,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,($10,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,($12,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,($14,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,($16,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,($18,a0) + add.l d1,d0 + move.l d0,d4 + swap d4 + ext.l d4 + move.w d4,($1A,a0) + add.l d1,d0 + swap d0 + ext.l d0 + move.w d0,($1C,a0) + lea ($20,a0),a0 + cmpa.l a1,a0 + bne.w lbC002804 + lea (lbW004484,pc),a0 + lea (lbW004682,pc),a1 +lbC0028DC: move.w d2,(a0)+ + addq.w #3,d2 + cmpa.l a1,a0 + beq.w lbC001DD8 + move.w d2,(a0)+ + addq.w #3,d2 + cmpa.l a1,a0 + bne.b lbC0028DC + bra.w lbC001DD8 + +lbC0028F2: move.w d3,d1 + sub.w d4,d1 +lbC0028F6: cmpi.w #$FF80,d1 + bge.b lbC00291E +lbC0028FC: moveq #-$80,d1 + move.b d1,(-1,a0) + cmpa.l a0,a1 + bne.w lbC002708 + bra.w lbC002774 + +lbC00290C: movea.w d4,a5 + suba.w d6,a5 + suba.w d5,a5 + suba.w d3,a5 + move.l a5,d1 + asr.l #1,d1 + cmpi.w #$FF80,d1 + blt.b lbC0028FC +lbC00291E: cmpi.w #$7F,d1 + ble.w lbC00276C + moveq #$7F,d1 + move.b d1,(-1,a0) + cmpa.l a0,a1 + bne.w lbC002708 + bra.w lbC002774 + +lbC002936: move.l a3,d1 + asr.l #8,d1 + not.b d1 + clr.w d2 + move.b d1,d2 + bra.w lbC00269A + +lbC002944: move.w d4,d1 + sub.w a5,d1 + bra.b lbC0028F6 + +lbC00294A: cmpa.w #0,a2 + bge.w lbC0037FE + lea (12,a2),a0 + cmpa.w #0,a0 + bge.w lbC0030A8 + lea ($18,a2),a0 + cmpa.w #0,a0 + bge.w lbC0030B4 + lea ($24,a2),a0 + cmpa.w #0,a0 + bge.w lbC0030FA + lea ($30,a2),a0 + cmpa.w #0,a0 + bge.w lbC003100 + lea ($3C,a2),a0 + cmpa.w #0,a0 + bge.w lbC003112 + lea ($48,a2),a0 + cmpa.w #0,a0 + bge.w lbC003118 + lea ($54,a2),a0 + cmpa.w #0,a0 + bge.w lbC00312A + lea ($60,a2),a0 + cmpa.w #0,a0 + bge.w lbC0032D4 + lea ($6C,a2),a0 + cmpa.w #0,a0 + bge.w lbC0032F4 + lea ($78,a2),a0 + cmpa.w #0,a0 + bge.w lbC0034EC + lea ($84,a2),a0 + moveq #-11,d1 + move.l a0,d0 + add.l a0,d0 + add.l a0,d0 + lsl.l #7,d0 + adda.l d0,a0 + adda.l ($78,sp),a0 + move.b ($14,a6),d2 + move.b d2,d0 + andi.b #3,d0 + beq.w lbC002410 +lbC0029EC: cmpi.b #1,d0 + bne.w lbC002AAA + lea ($100,a0),a3 + move.w d1,d0 + ext.l d0 + tst.w d1 + bgt.w lbC00241C +lbC002A02: tst.w d1 + beq.w lbC003806 + move.l d0,d3 + neg.l d3 + move.l #$8000,d6 + asr.l d3,d6 + move.b ($15,a6),($5C,sp) + move.b ($11,a6),($5E,sp) + moveq #0,d7 + move.b ($180,a0),d7 + move.b ($21,a6),d3 + andi.b #$10,d2 + move.b d2,($34,sp) + beq.w lbC002446 +lbC002A36: move.b d3,d2 + ext.w d2 + tst.b d3 + ble.w lbC003078 + move.b #1,($34,sp) + muls.w d2,d2 + bra.w lbC002452 + +lbC002A4C: move.b (a3),d4 + ext.w d4 + bra.w lbC002564 + +lbC002A54: movea.l d3,a0 + moveq #0,d0 + move.b ($5E,sp),d0 + move.l d6,-(sp) + move.l d0,-(sp) + move.l d1,($32,sp) + move.l a0,($36,sp) + movea.l ($40,sp),a1 + jsr (a1) + addq.l #8,sp + movea.l ($70,sp),a1 + move.l ($40,sp),d4 + pea (a1,d4.l) + move.l d0,-(sp) + movea.l ($40,sp),a1 + jsr (a1) + addq.l #8,sp + move.l d0,d4 + move.l d6,-(sp) + move.l ($4C,sp),-(sp) + movea.l ($40,sp),a1 + jsr (a1) + addq.l #8,sp + add.l d4,d0 + move.l ($2A,sp),d1 + movea.l ($2E,sp),a0 + cmp.l d7,d0 + bgt.w lbC002510 + bra.w lbC002516 + +lbC002AAA: cmpi.b #2,d0 + bne.w lbC002412 + lea ($80,a0),a3 + bra.w lbC002412 + +lbC002ABA: move.l d6,($34,sp) + move.l d0,d4 + sub.l d3,d4 + bmi.b lbC002B38 +lbC002AC4: moveq #15,d6 + asr.l d6,d4 + move.b (a3,d4.l),d4 + ext.w d4 +lbC002ACE: move.w ($48,sp),d6 + muls.w d4,d6 + move.b (a1),d4 + ext.w d4 + asr.l #7,d6 + add.w d6,d4 + cmpi.w #$7F,d4 + ble.b lbC002AE4 + moveq #$7F,d4 +lbC002AE4: addq.l #1,a1 + cmpi.w #$FF80,d4 + bge.b lbC002AEE + moveq #-$80,d4 +lbC002AEE: move.b d4,(-1,a1) + add.l d1,d0 + cmp.l d7,d0 + blt.b lbC002B0C + sub.l d7,d0 + add.l d5,d3 + cmpa.l d3,a5 + bgt.b lbC002B04 + neg.l d5 + move.l a5,d3 +lbC002B04: cmp.l a0,d3 + bgt.b lbC002B0C + neg.l d5 + move.l a0,d3 +lbC002B0C: tst.l d2 + beq.b lbC002B2A + adda.l d2,a2 + move.l a2,d1 + moveq #10,d4 + asr.l d4,d1 + add.l ($34,sp),d1 + move.l d2,d4 + asr.l #7,d4 + sub.l d4,d2 + cmp.l d7,d1 + bcs.b lbC002B2A + moveq #0,d2 + moveq #0,d1 +lbC002B2A: cmpa.l ($44,sp),a1 + beq.w lbC0025C0 + move.l d0,d4 + sub.l d3,d4 + bpl.b lbC002AC4 +lbC002B38: move.b (a3),d4 + ext.w d4 + bra.b lbC002ACE + +lbC002B3E: move.l #$8000,d5 + tst.w d1 + blt.w lbC002C12 +lbC002B4A: tst.l ($54,sp) + beq.w lbC0025C0 + clr.w d0 + move.b ($5C,sp),d0 + clr.w d1 + move.b ($5E,sp),d1 + add.w d1,d0 + addq.w #1,d0 + movea.l d5,a1 + movea.l ($50,sp),a5 + clr.b d1 + moveq #0,d4 + movea.l #$8000,a0 + clr.w d3 + move.b ($69,sp),d3 + cmpa.w #$7FFF,a0 + bgt.b lbC002BBA +lbC002B7E: move.b d1,(a5)+ + adda.l a1,a0 + tst.l d2 + beq.b lbC002BAC + add.l d2,d4 + move.l d4,d6 + moveq #10,d7 + asr.l d7,d6 + movea.l d6,a1 + adda.l d5,a1 + tst.b ($34,sp) + beq.b lbC002B9E + move.l d2,d6 + asr.l #7,d6 + sub.l d6,d2 +lbC002B9E: cmpa.w #$1FF,a1 + bgt.b lbC002BAC + moveq #0,d2 + suba.l a0,a0 + movea.w #$200,a1 +lbC002BAC: cmpa.l ($44,sp),a5 + beq.w lbC0025C0 + cmpa.w #$7FFF,a0 + ble.b lbC002B7E +lbC002BBA: move.w d0,d1 + moveq #13,d6 + lsl.w d6,d1 + eor.w d1,d0 + move.w d0,d1 + moveq #9,d7 + lsr.w d7,d1 + eor.w d1,d0 + move.w d0,d1 + lsl.w #7,d1 + eor.w d1,d0 + cmpa.l #$8000,a0 + beq.b lbC002BF0 + move.l a0,d6 + addi.l #$FFFF8000,d6 + move.l a0,d1 + addi.l #$FFFF7FFF,d1 + andi.w #$8000,d1 + movea.l d6,a0 + suba.l d1,a0 +lbC002BF0: move.b d0,d1 + ext.w d1 + move.w d3,d6 + muls.w d1,d6 + move.l d6,d1 + asr.l #7,d1 + cmpi.w #$7F,d1 + ble.b lbC002C04 + moveq #$7F,d1 +lbC002C04: cmpi.w #$FF80,d1 + bge.b lbC002C0C + moveq #-$80,d1 +lbC002C0C: add.b (a5),d1 + bra.w lbC002B7E + +lbC002C12: move.l a2,d3 + neg.l d3 + pea (12).w + move.l d3,-(sp) + movea.l ($68,sp),a0 + jsr (a0) + addq.l #8,sp + cmpi.w #$FFFF,d0 + beq.w lbC0037AA +lbC002C2C: asr.l #1,d5 + dbra d0,lbC002C2C + pea (12).w + move.l d5,-(sp) + movea.l ($68,sp),a1 + jsr (a1) + addq.l #8,sp + moveq #0,d4 + move.w d0,d4 + pea (12).w + move.l d3,-(sp) + lea (lbC003B74,pc),a0 + jsr (a0) + addq.l #8,sp + andi.l #$FFFF,d0 + move.l d4,-(sp) + moveq #12,d1 + sub.l d0,d1 + move.l d1,-(sp) + movea.l ($40,sp),a0 + jsr (a0) + addq.l #8,sp + add.l d0,d5 + bra.w lbC002B4A + +lbC002C6E: lea ($40,a2),a1 + move.w d3,d7 + sub.w d5,d7 + muls.w d0,d7 + move.b (a5)+,d1 + ext.w d1 + asr.l #8,d7 + add.w d7,d1 + sub.w d3,d1 + move.w d2,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + add.w d1,d3 + move.w d3,d1 + sub.w d5,d1 + move.w d2,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + add.w d1,d5 + move.w d5,d1 + sub.w d6,d1 + move.w d2,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + add.w d1,d6 + move.w d6,d1 + sub.w d4,d1 + move.w d2,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + add.w d1,d4 + move.w d4,d1 + cmpi.w #$FF80,d4 + bge.b lbC002D16 +lbC002CBE: moveq #-$80,d1 +lbC002CC0: move.b d1,(-1,a5) + cmpa.l a5,a1 + beq.w lbC002774 +lbC002CCA: move.w d3,d7 + sub.w d5,d7 + muls.w d0,d7 + move.b (a5)+,d1 + ext.w d1 + asr.l #8,d7 + add.w d7,d1 + sub.w d3,d1 + move.w d2,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + add.w d1,d3 + move.w d3,d1 + sub.w d5,d1 + move.w d2,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + add.w d1,d5 + move.w d5,d1 + sub.w d6,d1 + move.w d2,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + add.w d1,d6 + move.w d6,d1 + sub.w d4,d1 + move.w d2,d7 + muls.w d1,d7 + move.l d7,d1 + asr.l #8,d1 + add.w d1,d4 + move.w d4,d1 + cmpi.w #$FF80,d4 + blt.b lbC002CBE +lbC002D16: cmpi.w #$7F,d4 + ble.b lbC002CC0 + moveq #$7F,d1 + move.b d1,(-1,a5) + cmpa.l a5,a1 + bne.b lbC002CCA + bra.w lbC002774 + +lbC002D2A: cmpi.l #$FF00,d0 + bgt.w lbC002936 + cmpa.l #$FEFF,a3 + ble.w lbC002936 + neg.l ($38,sp) + clr.w d2 + clr.b d1 + movea.l #$FF00,a3 + bra.w lbC00269A + +lbC002D50: move.b ($29,a6),d1 + andi.b #$20,d1 + move.b d1,($44,sp) + bne.b lbC002D66 + tst.b ($26,a6) + bne.w lbC00329A +lbC002D66: move.b ($1B,a6),d0 + bne.w lbC0030C0 + cmpi.b #$FF,($1E,a6) + beq.w lbC002F28 + move.b ($14,a6),d2 + andi.b #$20,d2 + move.b ($14,a6),d0 + andi.b #8,d0 + move.b d0,($38,sp) + move.w ($56,sp),d4 + moveq #2,d0 + swap d0 + move.l #$1000000,d3 +lbC002D9A: tst.b d2 + beq.b lbC002DA0 + lsl.l #4,d0 +lbC002DA0: tst.w d4 + beq.w lbC0037DA + subq.w #1,d4 + add.l d0,d3 + cmpi.l #$FFFFFF,d3 + bgt.w lbC0037E6 + movea.l ($50,sp),a0 + tst.b ($38,sp) + bne.w lbC002EFC + movea.l a0,a1 + move.b (a1)+,d5 + ext.w d5 + move.l d3,d1 + swap d1 + ext.l d1 + muls.w d5,d1 + asr.l #8,d1 + move.b d1,(a0) + tst.w d4 + beq.b lbC002DFC +lbC002DD6: subq.w #1,d4 + add.l d0,d3 + cmpi.l #$FFFFFF,d3 + bgt.w lbC0034A0 + movea.l a1,a0 + movea.l a0,a1 + move.b (a1)+,d5 + ext.w d5 + move.l d3,d1 + swap d1 + ext.l d1 + muls.w d5,d1 + asr.l #8,d1 + move.b d1,(a0) + tst.w d4 + bne.b lbC002DD6 +lbC002DFC: move.l d3,d0 + asr.l #8,d0 +lbC002E00: move.b ($1D,a6),d3 + beq.w lbC002F28 + clr.w d1 +lbC002E0A: clr.w d4 + move.b d3,d4 + move.w d4,d7 + mulu.w d4,d7 + lsr.l #2,d7 + add.w d4,d7 + tst.b d2 + bne.w lbC00345C + andi.l #$FF,d3 + moveq #12,d2 + lsl.l d2,d3 + move.l d3,d2 + clr.w d2 + swap d2 + movea.w d2,a3 + lea (lbW003C1C,pc),a0 + move.l d2,d4 + add.l d2,d4 + move.w (a0,d4.l),d4 + andi.l #$FFFF,d4 + movea.l d4,a5 + addq.l #1,d2 + add.l d2,d2 + move.w (a0,d2.l),d2 + andi.l #$FFFF,d2 + movea.l d2,a2 +lbC002E52: tst.w d1 + beq.w lbC002F28 + andi.l #$FFFF,d7 + clr.w d4 + lea (lbW003C1C,pc),a0 + move.l a0,($4C,sp) + movea.l d7,a0 + move.l a2,d7 + movea.l a0,a2 +lbC002E6E: subq.w #1,d1 + add.l a2,d3 + move.l d3,d2 + clr.w d2 + swap d2 + cmpi.l #$8E,d2 + bhi.b lbC002E98 + cmp.w a3,d2 + bhi.w lbC003406 + movea.w a5,a0 + move.w d7,d4 + move.w d4,d2 + sub.w a0,d2 + move.w d3,d4 + lsr.w #8,d4 + muls.w d2,d4 + asr.l #8,d4 + add.w a0,d4 +lbC002E98: moveq #0,d2 + move.w d4,d2 + sub.l d2,d0 + move.b ($1E,a6),d5 + moveq #0,d2 + move.b d5,d2 + lsl.l #8,d2 + movea.l a1,a0 + move.b (a0)+,d6 + ext.w d6 + cmp.l d0,d2 + bgt.w lbC00346C + move.l d0,d2 + asr.l #8,d2 + muls.w d6,d2 + tst.b ($38,sp) + beq.w lbC003400 + asr.l #6,d2 + cmpi.w #$7F,d2 + ble.w lbC0033F2 + moveq #$7F,d2 +lbC002ECE: move.b d2,(-1,a0) + tst.w d1 + beq.b lbC002F28 + movea.l a0,a1 + bra.b lbC002E6E + +lbC002EDA: cmpi.w #$FF80,d1 + bge.b lbC002EE2 + moveq #-$80,d1 +lbC002EE2: move.b d1,(-1,a1) + tst.w d4 + beq.w lbC002DFC + subq.w #1,d4 + add.l d0,d3 + cmpi.l #$FFFFFF,d3 + bgt.w lbC0032FA + movea.l a1,a0 +lbC002EFC: movea.l a0,a1 + move.b (a1)+,d5 + ext.w d5 + move.l d3,d1 + swap d1 + ext.l d1 + muls.w d5,d1 + asr.l #6,d1 + cmpi.w #$7F,d1 + ble.b lbC002EDA + moveq #$7F,d1 + bra.b lbC002EE2 + +lbC002F16: cmpi.w #$FF80,d0 + bge.b lbC002F1E + moveq #-$80,d0 +lbC002F1E: move.b d0,(-1,a0) + cmpa.l a0,a1 + bne.w lbC0033D0 +lbC002F28: tst.b ($44,sp) + beq.b lbC002F36 + tst.b ($26,a6) + bne.w lbC00327E +lbC002F36: move.b ($1A,a6),d0 + beq.w lbC002FF0 + subq.b #1,d0 + cmp.b ($6B,sp),d0 + beq.w lbC002FF0 + movea.l ($3C,sp),a1 + movea.l ($9F6,a1),a0 + clr.w d1 + move.b d0,d1 + mulu.w #$2A,d1 + movea.l ($9C,a0),a0 + adda.l d1,a0 + andi.l #$FF,d0 + addi.l #$27F,d0 + add.l d0,d0 + add.l d0,d0 + movea.l (a1,d0.l),a2 + moveq #0,d3 + move.b ($19,a0),d3 + addq.l #1,d3 + lsl.l #7,d3 + moveq #0,d4 + move.b ($19,a6),d4 + addq.l #1,d4 + lsl.l #7,d4 + move.l d3,d2 + cmp.l d3,d4 + bcs.w lbC0032B6 + btst #2,($14,a0) + beq.w lbC0032C2 +lbC002F98: btst #2,($14,a6) + beq.w lbC003648 + movea.l ($40,sp),a3 + move.l ($50,sp),d7 + moveq #0,d6 +lbC002FAC: tst.l d2 + beq.b lbC002FE0 + movea.l d7,a0 + movea.l a2,a1 + clr.w d1 +lbC002FB6: move.b (a0),d0 + ext.w d0 + move.b (a1)+,d5 + ext.w d5 + add.w d5,d0 + cmpi.w #$7F,d0 + ble.b lbC002FC8 + moveq #$7F,d0 +lbC002FC8: addq.l #1,a0 + cmpi.w #$FF80,d0 + bge.b lbC002FD2 + moveq #-$80,d0 +lbC002FD2: move.b d0,(-1,a0) + addq.w #1,d1 + moveq #0,d0 + move.w d1,d0 + cmp.l d0,d2 + bhi.b lbC002FB6 +lbC002FE0: lsr.l #1,d2 + adda.l d3,a2 + add.l d4,d7 + lsr.l #1,d3 + lsr.l #1,d4 + addq.l #1,d6 + cmpa.l d6,a3 + bne.b lbC002FAC +lbC002FF0: btst #2,($14,a6) + beq.b lbC003044 + moveq #0,d0 + move.b ($19,a6),d0 + addq.l #1,d0 + move.w #$80,d1 + mulu.w d0,d1 + movea.l ($50,sp),a0 + adda.l d1,a0 + lsr.l #1,d1 + moveq #3,d2 + move.l ($50,sp),d3 +lbC003014: tst.w d1 + beq.b lbC003036 + move.w d1,d0 + subq.w #1,d0 + andi.l #$FFFF,d0 + lea (1,a0,d0.l),a2 + movea.l d3,a1 +lbC003028: move.b (a1),(a0)+ + addq.l #2,a1 + cmpa.l a0,a2 + bne.b lbC003028 + addq.l #1,d0 + add.l d0,d0 + add.l d0,d3 +lbC003036: moveq #0,d0 + move.w d1,d0 + movea.l d3,a0 + adda.l d0,a0 + lsr.w #1,d1 + subq.w #1,d2 + bne.b lbC003014 +lbC003044: movea.l ($AC,sp),a1 + moveq #0,d0 + move.b (a1),d0 + move.l d0,d1 + subq.l #1,d1 + cmp.l ($64,sp),d1 + beq.w lbC003130 + addq.l #1,($64,sp) + cmp.l ($64,sp),d0 + bgt.w lbC002288 +lbC003064: movem.l (sp)+,d2-d7/a2/a3/a5/a6 + lea ($78,sp),sp + rts + +lbC00306E: ext.w d3 + move.w d3,d2 + ext.l d2 + bra.w lbC002452 + +lbC003078: moveq #2,d3 + lsl.l d0,d3 + muls.w d2,d3 + move.l d3,d2 + move.b #1,($34,sp) + bra.w lbC002452 + +lbC00308A: tst.l d0 + blt.w lbC002936 + cmpa.w #0,a3 + bgt.w lbC002936 + neg.l ($38,sp) + move.w #$FF,d2 + st d1 + suba.l a3,a3 + bra.w lbC00269A + +lbC0030A8: moveq #-1,d1 + bra.w lbC0023F4 + +lbC0030AE: moveq #1,d1 + bra.w lbC0023F4 + +lbC0030B4: moveq #-2,d1 + bra.w lbC0023F4 + +lbC0030BA: moveq #2,d1 + bra.w lbC0023F4 + +lbC0030C0: move.b ($14,a6),d2 + andi.b #$20,d2 + move.b ($14,a6),d1 + andi.b #8,d1 + move.b d1,($38,sp) + move.w ($56,sp),d4 + andi.l #$FF,d0 + move.l d0,-(sp) + move.l #$20000,-(sp) + movea.l ($68,sp),a0 + jsr (a0) + addq.l #8,sp + moveq #0,d3 + bra.w lbC002D9A + +lbC0030F4: moveq #3,d1 + bra.w lbC0023F4 + +lbC0030FA: moveq #-3,d1 + bra.w lbC0023F4 + +lbC003100: moveq #-4,d1 + bra.w lbC0023F4 + +lbC003106: moveq #4,d1 + bra.w lbC0023F4 + +lbC00310C: moveq #5,d1 + bra.w lbC0023F4 + +lbC003112: moveq #-5,d1 + bra.w lbC0023F4 + +lbC003118: moveq #-6,d1 + bra.w lbC0023F4 + +lbC00311E: moveq #6,d1 + bra.w lbC0023F4 + +lbC003124: moveq #7,d1 + bra.w lbC0023F4 + +lbC00312A: moveq #-7,d1 + bra.w lbC0023F4 + +lbC003130: movea.l ($3C,sp),a3 + move.b #1,($9FA,a3) + move.b ($9F3,a3),d0 + cmpi.b #$2F,d0 + bhi.w lbC0034FE + move.b d0,($9F4,a3) + move.l ($A5C,a3),d0 + move.l d0,($6C,a3) + move.w #2,($70,a3) + clr.b ($76,a3) + move.w #$7B,($74,a3) + move.b #$40,(6,a3) + clr.b (9,a3) + clr.w (10,a3) + clr.w (12,a3) + clr.l (a3) + clr.l ($5A,a3) + moveq #3,d1 + move.l d1,($40,a3) + clr.b (15,a3) + clr.w ($10,a3) + clr.w ($12,a3) + move.w #$FF,($14,a3) + move.l d0,($2E8,a3) + move.w #2,($2EC,a3) + clr.b ($2F2,a3) + move.w #$7B,($2F0,a3) + move.b #$40,($282,a3) + clr.b ($285,a3) + clr.w ($286,a3) + clr.w ($288,a3) + clr.l ($27C,a3) + clr.l ($2D6,a3) + move.l d1,($2BC,a3) + clr.b ($28B,a3) + clr.w ($28C,a3) + clr.w ($28E,a3) + move.w #$FF,($290,a3) + move.l d0,($564,a3) + move.w #2,($568,a3) + clr.b ($56E,a3) + move.w #$7B,($56C,a3) + move.b #$40,($4FE,a3) + clr.b ($501,a3) + clr.w ($502,a3) + clr.w ($504,a3) + clr.l ($4F8,a3) + clr.l ($552,a3) + move.l d1,($538,a3) + clr.b ($507,a3) + clr.w ($508,a3) + clr.w ($50A,a3) + move.w #$FF,($50C,a3) + move.l d0,($7E0,a3) + move.w #2,($7E4,a3) + clr.b ($7EA,a3) + move.w #$7B,($7E8,a3) + clr.w ($786,a3) + move.b #$40,($77A,a3) + clr.w ($784,a3) + clr.b ($77F,a3) + clr.b ($77D,a3) + clr.b ($781,a3) + clr.b ($77E,a3) + clr.b ($780,a3) + clr.l ($774,a3) + clr.l ($7CE,a3) + move.l d1,($7B4,a3) + move.w #$FF,($788,a3) + clr.b ($783,a3) + movea.l ($AC,sp),a0 + moveq #0,d0 + move.b (a0),d0 +lbC00326E: addq.l #1,($64,sp) + cmp.l ($64,sp),d0 + ble.w lbC003064 + bra.w lbC002288 + +lbC00327E: move.w ($56,sp),-(sp) + clr.w -(sp) + move.l ($54,sp),-(sp) + pea ($26,a6) + lea (lbC000040,pc),a0 + jsr (a0) + lea (12,sp),sp + bra.w lbC002F36 + +lbC00329A: move.w ($56,sp),-(sp) + clr.w -(sp) + move.l ($54,sp),-(sp) + pea ($26,a6) + lea (lbC000040,pc),a0 + jsr (a0) + lea (12,sp),sp + bra.w lbC002D66 + +lbC0032B6: move.l d4,d2 + btst #2,($14,a0) + bne.w lbC002F98 +lbC0032C2: movea.w #1,a3 + move.l a3,($40,sp) + move.l ($50,sp),d7 + moveq #0,d6 + bra.w lbC002FAC + +lbC0032D4: moveq #-8,d1 + bra.w lbC0023F4 + +lbC0032DA: moveq #8,d1 + bra.w lbC0023F4 + +lbC0032E0: movea.l d2,a3 + move.w ($5C,sp),d2 + move.b ($48,sp),d1 + bra.w lbC00269A + +lbC0032EE: moveq #9,d1 + bra.w lbC0023F4 + +lbC0032F4: moveq #-9,d1 + bra.w lbC0023F4 + +lbC0032FA: addq.l #2,a0 + move.b (a1),d1 + ext.w d1 +lbC003300: move.w #$FF,d0 + muls.w d1,d0 + asr.l #6,d0 + cmpi.w #$7F,d0 + ble.w lbC003492 + moveq #$7F,d0 +lbC003312: move.b d0,(a1) + moveq #0,d0 + move.b ($1C,a6),d0 + lsl.l #4,d0 + tst.w d4 + beq.w lbC0034E2 + lea (2,a1,d0.l),a1 + move.w #$FF,d3 +lbC00332A: move.w d4,d1 + subq.w #1,d1 + movea.l a0,a2 + move.b (a2)+,d0 + ext.w d0 + move.w d3,d6 + muls.w d0,d6 + move.l d6,d0 + asr.l #6,d0 + cmpi.w #$7F,d0 + ble.b lbC00335C + moveq #$7F,d0 +lbC003344: move.b d0,(-1,a2) + cmpa.l a1,a2 + beq.b lbC00336C +lbC00334C: move.w d1,d4 + movea.l a2,a0 + bne.b lbC00332A + movea.l a2,a1 + moveq #0,d0 + not.w d0 + bra.w lbC002E00 + +lbC00335C: cmpi.w #$FF80,d0 + bge.b lbC003344 + moveq #-$80,d0 + move.b d0,(-1,a2) + cmpa.l a1,a2 + bne.b lbC00334C +lbC00336C: move.b ($1D,a6),d3 + moveq #0,d0 + not.w d0 + tst.b d3 + bne.w lbC002E0A + tst.w d1 + beq.w lbC002F28 + move.w d4,d1 + subq.w #2,d1 + move.b ($1E,a6),d0 + moveq #0,d2 + move.b d0,d2 + lsl.l #8,d2 + addq.l #2,a0 + andi.w #$FF,d0 + move.b (a1),d3 + ext.w d3 + muls.w d3,d0 + tst.b ($38,sp) + beq.w lbC003638 + asr.l #6,d0 + cmpi.w #$7F,d0 + bgt.w lbC003792 + cmpi.w #$FF80,d0 + blt.w lbC00378A + move.b d0,(a1) +lbC0033B6: tst.w d1 + beq.w lbC002F28 + asr.l #8,d2 + subq.w #1,d1 + andi.l #$FFFF,d1 + lea (1,a0,d1.l),a1 + tst.b ($38,sp) + beq.b lbC00342E +lbC0033D0: move.b (a0)+,d0 + ext.w d0 + move.w d2,d3 + muls.w d0,d3 + move.l d3,d0 + asr.l #6,d0 + cmpi.w #$7F,d0 + ble.w lbC002F16 + moveq #$7F,d0 + move.b d0,(-1,a0) + cmpa.l a0,a1 + bne.b lbC0033D0 + bra.w lbC002F28 + +lbC0033F2: cmpi.w #$FF80,d2 + bge.w lbC002ECE + moveq #-$80,d2 + bra.w lbC002ECE + +lbC003400: asr.l #8,d2 + bra.w lbC002ECE + +lbC003406: movea.l d2,a0 + adda.l d2,a0 + movea.l ($4C,sp),a3 + move.w (a0,a3.l),d4 + movea.w d7,a0 + movea.l d7,a5 + moveq #0,d7 + move.w d4,d7 + movea.w d2,a3 + move.w d4,d2 + sub.w a0,d2 + move.w d3,d4 + lsr.w #8,d4 + muls.w d2,d4 + asr.l #8,d4 + add.w a0,d4 + bra.w lbC002E98 + +lbC00342E: move.b (a0)+,d0 + ext.w d0 + move.w d2,d1 + muls.w d0,d1 + move.l d1,d0 + asr.l #8,d0 + move.b d0,(-1,a0) + cmpa.l a1,a0 + beq.w lbC002F28 + move.b (a0)+,d0 + ext.w d0 + move.w d2,d1 + muls.w d0,d1 + move.l d1,d0 + asr.l #8,d0 + move.b d0,(-1,a0) + cmpa.l a1,a0 + bne.b lbC00342E + bra.w lbC002F28 + +lbC00345C: movea.w #$200,a2 + movea.w #$400,a5 + suba.l a3,a3 + moveq #0,d3 + bra.w lbC002E52 + +lbC00346C: andi.w #$FF,d5 + muls.w d6,d5 + tst.b ($38,sp) + beq.w lbC003640 + asr.l #6,d5 + cmpi.w #$7F,d5 + bgt.w lbC0037A2 + cmpi.w #$FF80,d5 + blt.w lbC00379A + move.b d5,(a1) + bra.w lbC0033B6 + +lbC003492: cmpi.w #$FF80,d0 + bge.w lbC003312 + moveq #-$80,d0 + bra.w lbC003312 + +lbC0034A0: addq.l #2,a0 + move.b (a1),d1 + ext.w d1 +lbC0034A6: move.w #$FF,d3 + move.w d3,d0 + muls.w d1,d0 + asr.l #8,d0 + move.b d0,(a1) + moveq #0,d0 + move.b ($1C,a6),d0 + lsl.l #4,d0 + tst.w d4 + beq.b lbC0034E2 + lea (2,a1,d0.l),a1 +lbC0034C2: move.w d4,d1 + subq.w #1,d1 + movea.l a0,a2 + move.b (a2)+,d0 + ext.w d0 + move.w d3,d5 + muls.w d0,d5 + move.l d5,d0 + asr.l #8,d0 + move.b d0,(a0) + cmpa.l a1,a2 + beq.w lbC00336C + move.w d1,d4 + movea.l a2,a0 + bne.b lbC0034C2 +lbC0034E2: movea.l a0,a1 + moveq #0,d0 + not.w d0 + bra.w lbC002E00 + +lbC0034EC: moveq #-10,d1 + bra.w lbC0023F4 + +lbC0034F2: move.w ($5E,sp),d2 + move.b ($58,sp),d1 + bra.w lbC00269A + +lbC0034FE: btst #0,($9F0,a3) + beq.w lbC00365C + andi.b #15,d0 + move.b d0,($9F4,a3) + move.l ($A5C,a3),d0 + move.l d0,($6C,a3) + move.w #2,($70,a3) + clr.b ($76,a3) + move.w #$7B,($74,a3) + move.b #$40,(6,a3) + clr.b (9,a3) + clr.w (10,a3) + clr.w (12,a3) + clr.l (a3) + clr.l ($5A,a3) + moveq #3,d1 + move.l d1,($40,a3) + clr.b (15,a3) + clr.w ($10,a3) + clr.w ($12,a3) + move.w #$FF,($14,a3) + move.l d0,($2E8,a3) + move.w #2,($2EC,a3) + clr.b ($2F2,a3) + move.w #$7B,($2F0,a3) + move.b #$40,($282,a3) + clr.b ($285,a3) + clr.w ($286,a3) + clr.w ($288,a3) + clr.l ($27C,a3) + clr.l ($2D6,a3) + move.l d1,($2BC,a3) + clr.b ($28B,a3) + clr.w ($28C,a3) + clr.w ($28E,a3) + move.w #$FF,($290,a3) + move.l d0,($564,a3) + move.w #2,($568,a3) + clr.b ($56E,a3) + move.w #$7B,($56C,a3) + move.b #$40,($4FE,a3) + clr.b ($501,a3) + clr.w ($502,a3) + clr.w ($504,a3) + clr.l ($4F8,a3) + clr.l ($552,a3) + move.l d1,($538,a3) + clr.b ($507,a3) + clr.w ($508,a3) + clr.w ($50A,a3) + move.w #$FF,($50C,a3) + move.l d0,($7E0,a3) + move.w #2,($7E4,a3) + clr.b ($7EA,a3) + move.w #$7B,($7E8,a3) + clr.w ($786,a3) + move.b #$40,($77A,a3) + clr.w ($784,a3) + clr.b ($77F,a3) + clr.b ($77D,a3) + clr.b ($781,a3) + clr.b ($77E,a3) + clr.b ($780,a3) + clr.l ($774,a3) + clr.l ($7CE,a3) + move.l d1,($7B4,a3) + move.w #$FF,($788,a3) + clr.b ($783,a3) + movea.l ($AC,sp),a0 + moveq #0,d0 + move.b (a0),d0 + bra.w lbC00326E + +lbC003638: asr.l #8,d0 + move.b d0,(a1) + bra.w lbC0033B6 + +lbC003640: asr.l #8,d5 + move.b d5,(a1) + bra.w lbC0033B6 + +lbC003648: movea.w #1,a0 + move.l a0,($40,sp) + movea.l a0,a3 + move.l ($50,sp),d7 + moveq #0,d6 + bra.w lbC002FAC + +lbC00365C: lsr.b #4,d0 + move.b d0,($9F4,a3) + move.l ($A5C,a3),d0 + move.l d0,($6C,a3) + move.w #2,($70,a3) + clr.b ($76,a3) + move.w #$7B,($74,a3) + move.b #$40,(6,a3) + clr.b (9,a3) + clr.w (10,a3) + clr.w (12,a3) + clr.l (a3) + clr.l ($5A,a3) + moveq #3,d1 + move.l d1,($40,a3) + clr.b (15,a3) + clr.w ($10,a3) + clr.w ($12,a3) + move.w #$FF,($14,a3) + move.l d0,($2E8,a3) + move.w #2,($2EC,a3) + clr.b ($2F2,a3) + move.w #$7B,($2F0,a3) + move.b #$40,($282,a3) + clr.b ($285,a3) + clr.w ($286,a3) + clr.w ($288,a3) + clr.l ($27C,a3) + clr.l ($2D6,a3) + move.l d1,($2BC,a3) + clr.b ($28B,a3) + clr.w ($28C,a3) + clr.w ($28E,a3) + move.w #$FF,($290,a3) + move.l d0,($564,a3) + move.w #2,($568,a3) + clr.b ($56E,a3) + move.w #$7B,($56C,a3) + move.b #$40,($4FE,a3) + clr.b ($501,a3) + clr.w ($502,a3) + clr.w ($504,a3) + clr.l ($4F8,a3) + clr.l ($552,a3) + move.l d1,($538,a3) + clr.b ($507,a3) + clr.w ($508,a3) + clr.w ($50A,a3) + move.w #$FF,($50C,a3) + move.l d0,($7E0,a3) + move.w #2,($7E4,a3) + clr.b ($7EA,a3) + move.w #$7B,($7E8,a3) + clr.w ($786,a3) + move.b #$40,($77A,a3) + clr.w ($784,a3) + clr.b ($77F,a3) + clr.b ($77D,a3) + clr.b ($781,a3) + clr.b ($77E,a3) + clr.b ($780,a3) + clr.l ($774,a3) + clr.l ($7CE,a3) + move.l d1,($7B4,a3) + move.w #$FF,($788,a3) + clr.b ($783,a3) + movea.l ($AC,sp),a0 + moveq #0,d0 + move.b (a0),d0 + bra.w lbC00326E + +lbC00378A: moveq #-$80,d0 + move.b d0,(a1) + bra.w lbC0033B6 + +lbC003792: moveq #$7F,d0 + move.b d0,(a1) + bra.w lbC0033B6 + +lbC00379A: moveq #-$80,d5 + move.b d5,(a1) + bra.w lbC0033B6 + +lbC0037A2: moveq #$7F,d5 + move.b d5,(a1) + bra.w lbC0033B6 + +lbC0037AA: move.l #$AAA,d4 + pea (12).w + move.l d3,-(sp) + lea (lbC003B74,pc),a0 + jsr (a0) + addq.l #8,sp + andi.l #$FFFF,d0 + move.l d4,-(sp) + moveq #12,d1 + sub.l d0,d1 + move.l d1,-(sp) + movea.l ($40,sp),a0 + jsr (a0) + addq.l #8,sp + add.l d0,d5 + bra.w lbC002B4A + +lbC0037DA: move.l d3,d0 + asr.l #8,d0 + movea.l ($50,sp),a1 + bra.w lbC002E00 + +lbC0037E6: movea.l ($50,sp),a0 + move.b (a0)+,d1 + ext.w d1 + movea.l ($50,sp),a1 + tst.b ($38,sp) + beq.w lbC0034A6 + bra.w lbC003300 + +lbC0037FE: movea.l a2,a0 + clr.w d1 + bra.w lbC0023F4 + +lbC003806: move.l #$8000,d6 + bra.w lbC002424 + +lbC003810: movem.l d2-d4/a2,-(sp) + move.l ($14,sp),d0 + movea.l ($18,sp),a1 + move.l ($1C,sp),d1 + move.l d1,d3 + subq.l #1,d3 + tst.l d1 + beq.b lbC00388A + movea.l d0,a0 + addq.l #4,a0 + cmpa.l a1,a0 + sls d2 + neg.b d2 + lea (4,a1),a0 + cmpa.l d0,a0 + sls d4 + neg.b d4 + or.b d4,d2 + moveq #8,d4 + cmp.l d3,d4 + scs d4 + neg.b d4 + and.b d4,d2 + beq.b lbC003890 + move.l a1,d2 + or.l d0,d2 + moveq #3,d4 + and.l d4,d2 + bne.b lbC003890 + movea.l a1,a0 + movea.l d0,a2 + moveq #-4,d2 + and.l d1,d2 + add.l a1,d2 +lbC00385E: move.l (a0)+,(a2)+ + cmp.l a0,d2 + bne.b lbC00385E + moveq #-4,d2 + and.l d1,d2 + movea.l d0,a0 + adda.l d2,a0 + adda.l d2,a1 + sub.l d2,d3 + cmp.l d1,d2 + beq.b lbC00388A + move.b (a1),(a0) + tst.l d3 + beq.b lbC00388A + move.b (1,a1),(1,a0) + subq.l #1,d3 + beq.b lbC00388A + move.b (2,a1),(2,a0) +lbC00388A: movem.l (sp)+,d2-d4/a2 + rts + +lbC003890: movea.l d0,a0 + add.l a1,d1 +lbC003894: move.b (a1)+,(a0)+ + cmp.l a1,d1 + beq.b lbC00388A + move.b (a1)+,(a0)+ + cmp.l a1,d1 + bne.b lbC003894 + bra.b lbC00388A + +lbC0038A2: movem.l d2-d5/a2/a3,-(sp) + movea.l ($20,sp),a2 + movea.l ($24,sp),a1 + cmpi.b #$50,(a1) + bne.b lbC0038BC + cmpi.b #$52,(1,a1) + beq.b lbC0038C4 +lbC0038BC: moveq #0,d0 +lbC0038BE: movem.l (sp)+,d2-d5/a2/a3 + rts + +lbC0038C4: cmpi.b #$54,(2,a1) + bne.b lbC0038BC + move.b (3,a1),d2 + cmpi.b #$1B,d2 + bhi.b lbC0038BC + move.b ($3F,a1),d0 + move.b d0,(1,a2) + move.b ($41,a1),d1 + move.b d1,(a2) + andi.w #$FF,d0 + move.w d0,(2,a2) + moveq #0,d3 + move.b (4,a1),d3 + lsl.w #8,d3 + swap d3 + clr.w d3 + moveq #0,d0 + move.b (5,a1),d0 + swap d0 + clr.w d0 + or.l d0,d3 + moveq #0,d0 + move.b (6,a1),d0 + lsl.l #8,d0 + or.l d3,d0 + or.b (7,a1),d0 + moveq #0,d3 + move.b ($3C,a1),d3 + moveq #0,d4 + move.b ($3E,a1),d4 + move.l d4,($8C,a2) + add.l a1,d0 + move.l d0,($94,a2) + clr.l ($88,a2) + move.l d3,($90,a2) + move.b (8,a1),d3 + lsl.w #8,d3 + swap d3 + clr.w d3 + moveq #0,d0 + move.b (9,a1),d0 + swap d0 + clr.w d0 + or.l d0,d3 + moveq #0,d0 + move.b (10,a1),d0 + lsl.l #8,d0 + or.l d3,d0 + or.b (11,a1),d0 + add.l a1,d0 + move.l d0,(4,a2) + moveq #0,d3 + move.b (12,a1),d3 + lsl.w #8,d3 + swap d3 + clr.w d3 + moveq #0,d0 + move.b (13,a1),d0 + swap d0 + clr.w d0 + or.l d0,d3 + moveq #0,d0 + move.b (14,a1),d0 + lsl.l #8,d0 + or.l d3,d0 + or.b (15,a1),d0 + lea (a1,d0.l),a0 + moveq #$20,d0 +lbC003986: lea ($17,a0),a3 +lbC00398A: tst.b (a0)+ + beq.b lbC003992 + cmpa.l a0,a3 + bne.b lbC00398A +lbC003992: subq.l #1,d0 + bne.b lbC003986 + move.l a0,($98,a2) + move.b ($40,a1),d0 + moveq #0,d5 + move.b d0,d5 + move.l d5,d4 + lsl.l #3,d4 + add.l a0,d4 + tst.b d0 + beq.b lbC0039CC + lea (8,a2),a3 + addq.l #7,a0 + add.l d5,d5 + add.l d5,d5 + add.l a3,d5 +lbC0039B8: move.l d4,(a3)+ + moveq #0,d3 + move.b (a0),d3 + move.l d3,d0 + add.l d3,d0 + add.l d3,d0 + add.l d0,d4 + addq.l #8,a0 + cmp.l a3,d5 + bne.b lbC0039B8 +lbC0039CC: moveq #0,d3 + move.b ($10,a1),d3 + lsl.w #8,d3 + swap d3 + clr.w d3 + moveq #0,d0 + move.b ($11,a1),d0 + swap d0 + clr.w d0 + or.l d0,d3 + moveq #0,d0 + move.b ($12,a1),d0 + lsl.l #8,d0 + or.l d3,d0 + or.b ($13,a1),d0 + lea (a1,d0.l),a0 + moveq #$18,d0 +lbC0039F8: lea ($17,a0),a3 + move.l a0,d3 + tst.b (a0)+ + beq.b lbC003A0C +lbC003A02: cmpa.l a0,a3 + beq.b lbC003A0C + move.l a0,d3 + tst.b (a0)+ + bne.b lbC003A02 +lbC003A0C: subq.l #1,d0 + bne.b lbC0039F8 + move.l a0,d0 + btst #0,d0 + bne.w lbC003AA8 +lbC003A1A: move.l a0,($9C,a2) + cmpi.b #$19,d2 + bhi.w lbC003AB0 + moveq #0,d0 + lea ($96C,a2),a0 +lbC003A2C: move.b d0,(a0,d0.l) + addq.l #1,d0 + moveq #$18,d2 + cmp.l d0,d2 + bne.b lbC003A2C +lbC003A38: tst.b d1 + beq.b lbC003AA0 + movea.w #$14,a0 + adda.l ($9C,a2),a0 + andi.w #$FF,d1 + mulu.w #$2A,d1 + lea (a0,d1.l),a2 + moveq #2,d0 +lbC003A52: moveq #0,d1 + move.b (5,a0),d1 + addq.l #1,d1 + lsl.l #7,d1 + btst #2,(a0) + beq.b lbC003A90 +lbC003A62: move.l d1,d2 + lsr.l #2,d2 + move.l d1,d3 + lsr.l #1,d3 + movea.l d2,a1 + adda.l d3,a1 + adda.l d1,a1 + lsr.l #3,d1 + add.l a1,d1 + add.l d1,d0 + lea ($2A,a0),a0 + cmpa.l a2,a0 + beq.w lbC0038BE + moveq #0,d1 + move.b (5,a0),d1 + addq.l #1,d1 + lsl.l #7,d1 + btst #2,(a0) + bne.b lbC003A62 +lbC003A90: add.l d1,d0 + lea ($2A,a0),a0 + cmpa.l a2,a0 + bne.b lbC003A52 + movem.l (sp)+,d2-d5/a2/a3 + rts + +lbC003AA0: moveq #2,d0 + movem.l (sp)+,d2-d5/a2/a3 + rts + +lbC003AA8: movea.l d3,a0 + addq.l #2,a0 + bra.w lbC003A1A + +lbC003AB0: pea ($18).w + pea ($42,a1) + pea ($96C,a2) + lea (lbC003810,pc),a0 + jsr (a0) + move.b (a2),d1 + lea (12,sp),sp + bra.w lbC003A38 + +lbC003ACC: move.w (4,sp),d0 + mulu.w (10,sp),d0 + move.w (6,sp),d1 + mulu.w (8,sp),d1 + add.w d1,d0 + swap d0 + clr.w d0 + move.w (6,sp),d1 + mulu.w (10,sp),d1 + add.l d1,d0 + rts + +lbC003AEE: move.l d2,-(sp) + move.l (12,sp),d1 + move.l (8,sp),d0 + cmpi.l #$10000,d1 + bcc.b lbC003B16 + move.l d0,d2 + clr.w d2 + swap d2 + divu.w d1,d2 + move.w d2,d0 + swap d0 + move.w (10,sp),d2 + divu.w d1,d2 + move.w d2,d0 + bra.b lbC003B46 + +lbC003B16: move.l d1,d2 +lbC003B18: lsr.l #1,d1 + lsr.l #1,d0 + cmpi.l #$10000,d1 + bcc.b lbC003B18 + divu.w d1,d0 + andi.l #$FFFF,d0 + move.l d2,d1 + mulu.w d0,d1 + swap d2 + mulu.w d0,d2 + swap d2 + tst.w d2 + bne.b lbC003B44 + add.l d2,d1 + bcs.b lbC003B44 + cmp.l (8,sp),d1 + bls.b lbC003B46 +lbC003B44: subq.l #1,d0 +lbC003B46: move.l (sp)+,d2 + rts + +lbC003B4A: move.l d2,-(sp) + moveq #1,d2 + move.l (12,sp),d1 + bpl.b lbC003B58 + neg.l d1 + neg.b d2 +lbC003B58: move.l (8,sp),d0 + bpl.b lbC003B62 + neg.l d0 + neg.b d2 +lbC003B62: move.l d1,-(sp) + move.l d0,-(sp) + bsr.b lbC003AEE + addq.l #8,sp + tst.b d2 + bpl.b lbC003B70 + neg.l d0 +lbC003B70: move.l (sp)+,d2 + rts + +lbC003B74: move.l (8,sp),d1 + move.l (4,sp),d0 + move.l d1,-(sp) + move.l d0,-(sp) + bsr.b lbC003B4A + addq.l #8,sp + move.l (8,sp),d1 + move.l d1,-(sp) + move.l d0,-(sp) + bsr.w lbC003ACC + addq.l #8,sp + move.l (4,sp),d1 + sub.l d0,d1 + move.l d1,d0 + rts + + move.l (8,sp),d1 + move.l (4,sp),d0 + move.l d1,-(sp) + move.l d0,-(sp) + bsr.w lbC003AEE + addq.l #8,sp + move.l (8,sp),d1 + move.l d1,-(sp) + move.l d0,-(sp) + bsr.w lbC003ACC + addq.l #8,sp + move.l (4,sp),d1 + sub.l d0,d1 + move.l d1,d0 + rts + + move.l a6,-(sp) + movea.l (4).w,a6 + jsr (-516,a6) + movea.l (sp)+,a6 + rts + +lbW003BD4: dc.w $8000,$871D,$8F2F,$97B7,$9FC4,$A9DE,$B505,$BF49 + dc.w $CB31,$D645,$E215,$F1A0 +lbB003BEC: dc.b 2,3,4,5,6,7,8,9,10,11,12,13,14,$14,$28,$50 +lbB003BFC: dc.b 0,8,9,10,11,12,13,14,$12,$14,$1C,$28,$32,$46,$A0 + dc.b $FF +lbB003C0C: dc.b 0,4,8,10,12,14,$10,$12,$14,$18,$20,$28,$38,$60 + dc.b $96,$FF +lbW003C1C: dc.w $400,$200,$180,$140,$100,$C0,$A0,$80,$78,$74,$6E + dc.w $69,$64,$5A,$46,$40,$38,$30,$28,$20,$1F,$1E,$1D + dc.w $1C,$1B,$1A,$19,$18,$17,$16,$15,$14,$13,$12,$11 + dc.w $10,15,14,13,13,12,12,11,11,10,10,9,9,8,8,8,8,7,7 + dc.w 7,7,6,6,6,6,5,5,5,5,4,4,4,4,4,4,4,4,4,4,3,4,4,3,4 + dc.w 4,3,4,3,4,3,4,3,4,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3 + dc.w 2,3,3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,2,2,2,2,2,2,2,1 + dc.w 2,1,2,1,2,1,2,1,1,2,1,1,1,2,1 +lbB003D3C: dc.b 0,1,3,6,7,9,10,11,12,13,14,$10,$13,$23,$37,$8F +lbW003D4C: dc.w $400,$200,$80,$64,$50,$40,$30,$20,$10,14,12,10,8 + dc.w 4,2,1 +lbB003D6C: dc.b 12,12,12,12,12,12,12,12,12,12,12,12,$18,$18,$18 + dc.b $18,$18,$18,$18,$18,$18,$18,$18,$18,$24,$24,$24 + dc.b $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 + dc.b $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 + dc.b $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 + dc.b $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 + dc.b $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 + dc.b $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 + dc.b $24,$24,0,0,0,0,0,0,0 +lbB003DD8: dc.b 1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3 + dc.b 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 + dc.b 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 + dc.b 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0 + dc.b 0,0,0,0,0,0,0,0 +lbB003E44: dc.b $FC,$FB,$FF,1,2,3,4,0 +lbW003E4C: dc.w 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,14,13,12 + dc.w 11,10,9,8,7,6,5,4,3,2,1,0 +lbW003E8C: dc.w $4D,$125,$21B,$437,$539,$755,$96D,$BD7,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +lbW004000: dc.w $350 +lbW004002: dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$320,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,$2F2,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,$2C8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$2A0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,$279,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,$256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$236,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,$216,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,$1F8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w $1DC,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$1C0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,$1A8,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,$190,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$179,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,$164,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,$151,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w $13E,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$12C,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,$11B,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,$10B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$FC,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,$EE,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,$E0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$D4,0 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,$C8,0,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,$BD,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$B2 + dc.w 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$A8,0,0,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,$9F,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w $96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$8D,0,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,$86,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,$7E,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$78,0,0,0,0,0 + dc.w 0,0,0,0,0,0,0,0,0,0,$71,0,0,0,0,0,0,0,0,0,0,0,0,0 + dc.w 0,0,$71 +lbW004482: dc.w 0 +lbW004484: dcb.w $3F,0 + dcb.w $3F,0 + dcb.w $3F,0 + dcb.w $3F,0 + dcb.w 3,0 +lbW004682: dc.w 0 + + end diff --git a/original/player.bin b/original/player.bin new file mode 100644 index 0000000000000000000000000000000000000000..0205580037640ce441d0059e17b40e59e8a2b4a5 GIT binary patch literal 18052 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 aY2cftfj3SAfAaqjK27t#fdBue!2brx4#>Iy literal 0 HcmV?d00001 diff --git a/original/player.bin.rs b/original/player.bin.rs new file mode 100644 index 0000000000000000000000000000000000000000..4fb4e0017889d201c3d950dd519e3ad10587d7d1 GIT binary patch literal 68004 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 literal 0 HcmV?d00001 diff --git a/original/player.i b/original/player.i new file mode 100644 index 0000000..455583c --- /dev/null +++ b/original/player.i @@ -0,0 +1,101 @@ +; MySong offsets +org_sv_num_waves_b = $00 +org_sv_num_steps_b = $01 +org_sv_num_steps_w = $02 +org_sv_patterns_ptr = $04 +org_sv_inst_patterns_table = $08 ; 32 ($18) waves max (until $88) +org_sv_curr_pat_pos_l = $88 ; only byte used FIXME why is this part of MySong? Should be in Player +org_sv_pat_pos_len_l = $8c ; only byte used +org_sv_pat_restart_pos_l = $90 ; only byte used +org_sv_pos_data_adr = $94 +org_sv_inst_infos_ptr = $98 +org_sv_waveinfo_ptr = $9c ; base pointer of wave info +org_sv_pattern_table = $a0 ; until $49c (excl.) +; $4d0 bytes of nothing here +org_sv_wavegen_order_table = $96c ; 24 bytes + +; ---------------------------------------- + +; channel structure +org_pcd_arp_notes_l = 0 +org_pcd_arp_note_1_b = 0 +org_pcd_arp_note_2_b = 1 +org_pcd_arp_note_3_b = 2 +org_pcd_last_trigger_pos_w = 4 ; I think this makes sure that we don't retrigger the note on same pos +org_pcd_pat_vol_b = 6 ; Multiplied with volume of instrument. +org_pcd_pat_portamento_speed_b = 7 +org_pcd_pat_adsr_rel_delay_b = 8 ; counts down until adsr release. Seems unused? +org_pcd_pat_2nd_inst_num_b = 9 +org_pcd_pat_2nd_inst_delay_b = 10 ; low byte only? +org_pcd_pat_vol_ramp_speed_b = 11 +org_pcd_new_inst_num_b = 12 ; load new instrument (number) +org_pcd_wave_offset_b = 13 +org_pcd_note_off_delay_b = 14 ; time before note is released ($ff = disabled) +org_pcd_note_delay_b = 15 ; $ff = no note delay +org_pcd_pat_portamento_dest_w = $10 ; portamento destination pitch +org_pcd_pat_pitch_slide_w = $12 +org_pcd_track_delay_steps_b = $14 ; $00 = no track delay, $ff = stop track delay (this is for the next channel!) +org_pcd_track_delay_offset_b = $15 ; $ff = no track delay +org_pcd_track_delay_vol16_b = $16 + +org_pcd_inst_vol_w = $18 +org_pcd_inst_num_w = $1a ; current instrument number (lower byte used) +org_pcd_inst_wave_num_w = $1c ; current wave number (1 based) (lower byte used) +org_pcd_loaded_inst_vol_w = $1e ; low byte only +org_pcd_inst_sel_arp_note_w = $20 +org_pcd_inst_new_step_w = $22 ; seems to be unused +org_pcd_inst_ping_pong_s_w = $24 ; direction of pingpong (-1 / +1) +org_pcd_inst_pitch_pinned_b = $26 +org_pcd_inst_vol_slide_w = $28 +org_pcd_inst_pitch_w = $2a +org_pcd_inst_curr_port_pitch_w = $2c +org_pcd_inst_note_pitch_w = $2e +org_pcd_inst_pitch_slide_w = $30 +org_pcd_inst_subloop_wait_w = $32 +org_pcd_inst_loop_offset_l = $34 ; only lower word reasonable +org_pcd_inst_info_ptr = $38 ; pointer to currently active instrument + +org_pcd_waveinfo_ptr = $3c ; pointer to currently active waveinfo +org_pcd_adsr_phase_l = $40 ; 0=attack, 1=decay, 2=sustain, 3=release +org_pcd_adsr_phase_speed_b = $44 ; +org_pcd_adsr_pos_w = $46 ; $10 (release pos?) +org_pcd_adsr_vol64_w = $48 ; speed? ($48)+($46) +org_pcd_adsr_attack_speed_l = $4a ; (low byte only) +org_pcd_adsr_decay_speed_l = $4e ; (low byte only) +org_pcd_adsr_sustain_l = $52 ; 15/16 (low byte only) +org_pcd_adsr_release_l = $56 ; read in release (low byte only) +org_pcd_adsr_volume_l = $5a ; 0 for restart / $400 (word only) +org_pcd_adsr_trigger_b = $5e ; 1 for restart (FIXME: never read??) +org_pcd_vibrato_pos_w = $60 ; +org_pcd_vibrato_depth_w = $62 ; is a byte value +org_pcd_vibrato_speed_w = $64 ; is a byte value +org_pcd_vibrato_delay_w = $66 ; is a byte value + +org_pcd_inst_step_pos_b = $68 +org_pcd_inst_speed_stop_b = $69 ; speed byte, $ff stops processing +org_pcd_inst_line_ticks_b = $6a ; $00 +org_pcd_channel_num_b = $6b +org_pcd_track_delay_buffer = $7c ; 16 bytes x 32 steps, until $27c + +org_pcd_out_ptr_l = $6c +org_pcd_out_len_w = $70 +org_pcd_out_lof_w = $72 +org_pcd_out_per_w = $74 +org_pcd_out_vol_b = $76 +org_pcd_out_trg_b = $77 +org_pcd_out_unused_l = $78 ; copied for track delay, but not used? +org_pcd_SIZEOF = $27c + +; player global variables (not bound to channel) +org_pv_pat_curr_row_b = $9f0 ; what is this? bit 0 is tested for shuffle +org_pv_next_pat_row_b = $9f1 +org_pv_next_pat_pos_b = $9f2 +org_pv_pat_speed_b = $9f3 ; speed byte (unfiltered) +org_pv_pat_line_ticks_b = $9f4 +org_pv_my_song = $9f6 ; fw_PretrackerMySong +org_pv_pat_stopped_b = $9fa ; 0 = stop, 1 = run + +org_pv_wave_sample_table = $9fc ; 24 pointers to sample starts, until $a5c +org_pv_sample_buffer_ptr = $a5c ; pointer to empty sample (for idle channel) +org_pv_osc_buffers = $a60 +org_pv_loop_pattern_b = $1c6c ; repeat current pattern, do not advance diff --git a/original/readme.txt b/original/readme.txt new file mode 100644 index 0000000..b3ae7a0 --- /dev/null +++ b/original/readme.txt @@ -0,0 +1,6 @@ +Here's the original player in binary form and resourced by hitchhikr +(his original archive does no longer seem to be available). + +I added a player.i include file with the "original offsets" of the +internal data structures, in case you want to fiddle with it. + diff --git a/src/drop_in_replacement.asm b/src/drop_in_replacement.asm new file mode 100644 index 0000000..92e5789 --- /dev/null +++ b/src/drop_in_replacement.asm @@ -0,0 +1,17 @@ +; vasmm68k_mot.exe -devpac -Fbin -o ..\binaries\raspberry_casket.bin -opt-allbra drop_in_replacement.asm + +PRETRACKER_SUPPORT_V1_5 = 0 +PRETRACKER_PARANOIA_MODE = 0 +PRETRACKER_DUBIOUS_PITCH_SHIFT_FOR_DELAYED_TRACK = 0 +PRETRACKER_KEEP_JUMP_TABLE = 1 +PRETRACKER_SONG_END_DETECTION = 0 +PRETRACKER_PROGRESS_SUPPORT = 0 +PRETRACKER_FASTER_CODE = 1 +PRETRACKER_VOLUME_TABLE = 1 +PRETRACKER_BUGFIX_CODE = 1 +PRETRACKER_DONT_TRASH_REGS = 1 +PRETRACKER_COPPER_OUTPUT = 0 + + opt p+,o+ + + include "raspberry_casket.asm" diff --git a/src/raspberry_casket.asm b/src/raspberry_casket.asm new file mode 100755 index 0000000..4ac048d --- /dev/null +++ b/src/raspberry_casket.asm @@ -0,0 +1,4253 @@ +;-------------------------------------------------------------------- +; Raspberry Casket Player V1.0 (26-Dec-2022) +; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; +; Provided by Chris 'platon42' Hodges +; +; Rewritten by platon42/Desire based on a resourced, binary identical +; version of the original Pretracker V1.0 replayer binary provided +; by hitchhikr (thanks!), originally written in C by Pink/Abyss. +; +; This version is the hard work of reverse engineering all the +; offsets, removing all the C compiler crud, removing dead and +; surplus code (maybe artefacts from earlier ideas that did nothing), +; optimizing the code where possible. This resulted in both reduced +; size of the replayer, faster sample calculation and speeding the +; tick routine up significantly. +; +; I also added a few optional features that come in handy, such as +; song-end detection and precalc progress support. +; +; It took me more than a month and it was not fun. +; +; Also: Open source. It's 2022, keeping the code closed is just not +; part of the demoscene spirit (anymore?), at least for a replayer. +; +; Also note that this is not the final state of the source code. +; I could go over many places still and try to rework them. +; But I wanted the code to be out in public. +; +; Verification +; ~~~~~~~~~~~~ +; The replayer has been verified on about 60 Pretracker tunes to +; create an identical internal state for each tick and identical +; samples (if certain optimizations switches are disabled). +; +; I might have introduced bugs though. If you find some problems, +; please let me know under chrisly@platon42.de. Thank you. +; +; Usage +; ~~~~~ +; The new replayer comes as a drop-in binary replacement if you wish. +; In this case you will get faster sample generation (about 12% +; faster on 68000) and about 45% less CPU time spent. However, you +; won't get stuff as song-end detection and precalc progress this way. +; This mode uses the old CPU DMA wait that takes away 8 raster lines. +; +; If you want to get rid of the unnecessary waiting, you can switch +; to a copper driven audio control. If you want to use the top portion +; of the copperlist for this, you probably need to double buffer it. +; Otherwise, you could also position the copperlist at the end of +; the display and use single buffering if you call the tick routine +; during the vertical blank. +; +; Please use the documented sizes for the MySong and MyPlayer data +; structures, which are the symbols sv_SIZEOF and pv_SIZEOF +; respectively (about 2K and 12K with volume table). +; +; The source needs two common include files to compile (custom.i and +; dmabits.i). You should leave assembler optimizations enabled. +; +; (0. If you're using copper list mode, call pre_PrepareCopperlist.) +; +; 1. Call pre_SongInit with +; - a pointer to MySong (mv_SIZEOF) in a1 and +; - the music data in a2. +; It will return the amount of sample memory needed in d0. +; +; 2. Then call pre_PlayerInit with +; - a pointer to MyPlayer (pv_SIZEOF) in a0 +; - a pointer to chip memory sample buffer in a1 +; - the pointer to MySong in a2 +; - a pointer to a longword for progress information or null in a3 +; This will create the samples, too. +; +; 3. After that, regularly call pre_PlayerTick with MyPlayer in a0 +; and optionally the copperlist in a1 if you're using that mode). +; +; Size +; ~~~~ +; The original C compiled code was... just bad. The new binary is +; about 1/3 of the original one. +; +; The code has been also optimized in a way that it compresses better. +; The original code compressed with Blueberry's Shrinkler goes from +; 18052 bytes down to 9023 bytes. +; +; Raspberry Casket, depending on the features compiled in, is about +; 6374 bytes and goes down to ~4410 bytes (in isolation). +; +; So this means that the optimization is not just "on the outside". +; +; Timing +; ~~~~~~ +; Unfortunately, the replayer is still pretty slow and has high +; jitter compared to other standard music replayers. +; This means it may take up to 33 raster lines (14-19 on average) +; which is significant more than a standard Protracker replayer +; (the original one could take about 60 raster lines worst case and +; about 34 on average!). +; +; Watch out for Presto, the LightSpeedPlayer variant that should +; solve this problem. + +;-------------------------------------------------------------------- + +; Here come the various options for you to configure. +; +; To create an optimized drop-in replacement for the old V1.0 binary: +; PRETRACKER_SUPPORT_V1_5 = 0 +; PRETRACKER_PARANOIA_MODE = 0 +; PRETRACKER_DUBIOUS_PITCH_SHIFT_FOR_DELAYED_TRACK = 0 +; PRETRACKER_KEEP_JUMP_TABLE = 1 +; PRETRACKER_SONG_END_DETECTION = 0 +; PRETRACKER_PROGRESS_SUPPORT = 0 +; PRETRACKER_FASTER_CODE = 1 +; PRETRACKER_VOLUME_TABLE = 1 +; PRETRACKER_BUGFIX_CODE = 1 +; PRETRACKER_DONT_TRASH_REGS = 1 +; PRETRACKER_COPPER_OUTPUT = 0 + + +; This player was based on the V1.0 binary of the pretracker replayer +; and thus can only play files created with versions up to V1.0. +; Subsongs and sound effects are not supported. There is usually no +; use for this in an intro anyway. +; +; Enabling this switch will patch the song runtime to make it backward +; compatible with this replayer. Song data will be modified in memory. +; I would encourage you to still use V1.0 as the files saved with +; Pretracker V1.5 are unnecessarily bigger (about 458 bytes) and might +; lose some instrument names it seems. + IFND PRETRACKER_SUPPORT_V1_5 +PRETRACKER_SUPPORT_V1_5 = 0 + ENDC + +; The original binary had a lot of extra checks that I would consider +; paranoia. For example it handled songs without instruments, waves +; or patterns. +; It contains code that I think is unreachable and a relic of +; being used for the actual tracker itself (releasing notes after +; a delay, looping patterns instead of advancing song). +; Or for combinations of song stopping (F00) and note delay in the +; same step, which no sane musician would use. +; +; This switch gets rid of the code. If you find a song that doesn't +; work with this disabled, please let me know. + IFND PRETRACKER_PARANOIA_MODE +PRETRACKER_PARANOIA_MODE = 0 + ENDC + +; There is some pitch shifting applied during track delay by +; a maximum of one period -- depending on the delay value. +; I guess this might add some phasing to the sound (which would be +; only audible in a mono mix, I would think), but it comes with an +; extra multiplication per channel. +; If you really want that, enable this switch. + IFND PRETRACKER_DUBIOUS_PITCH_SHIFT_FOR_DELAYED_TRACK +PRETRACKER_DUBIOUS_PITCH_SHIFT_FOR_DELAYED_TRACK = 0 + ENDC + +; The binary comes with a jump table that has three official entry +; points. As you have the source, you could just bsr to the three +; functions (pre_SongInit, pre_PlayerInit, pre_PlayerTick) directly. +; If you want a drop-in (binary) replacement instead, enable this +; switch to get the jump table back. + IFND PRETRACKER_KEEP_JUMP_TABLE +PRETRACKER_KEEP_JUMP_TABLE = 0 + ENDC + +; The original Pretracker replayer does not come with a song-end +; detection. If you want to have that (e.g. for a music disk), enable +; this switch and check for pv_songend_detected_b (relative to the +; MyPlayer structure) which goes to true when song-end is reached. + IFND PRETRACKER_SONG_END_DETECTION +PRETRACKER_SONG_END_DETECTION = 0 + ENDC + +; Do you want to have information on the sample generation progress +; during the call to pre_PlayerInit? Then enable this and call w +; pre_PlayerInit with a pointer to a longword in a3. +; Please make sure yourself that the initial value is zero. +; It will be incremented by the number of samples (in bytes) +; for each waveform done. You can get the total number of samples +; from the (previously undocumented) return value of pre_SongInit. + IFND PRETRACKER_PROGRESS_SUPPORT +PRETRACKER_PROGRESS_SUPPORT = 0 + ENDC + +; Use slightly faster code and smaller for sample generation that +; might be off by 1 (rounding error) compared to the original code. + IFND PRETRACKER_FASTER_CODE +PRETRACKER_FASTER_CODE = 1 + ENDC + +; Use tables for volume calculation instead of multiplication. +; Is slightly faster on 68000 (about 11%), but probably has no +; benefit for 68020+ and needs about 3.5 KB more RAM (MyPlayer) +; and 40 bytes of code. + IFND PRETRACKER_VOLUME_TABLE +PRETRACKER_VOLUME_TABLE = 1 + ENDC + +; I found some obvious bugs in the code. This switch enables bugfixes, +; but the sound might not be exactly the same as in the tracker / +; original player (e.g. there is a bug in the volume envelope that +; will cause a pause in the decay curve that is not supposed to +; happen). + IFND PRETRACKER_BUGFIX_CODE +PRETRACKER_BUGFIX_CODE = 1 + ENDC + +; You want to take care of what registers may be trashed by these +; routines because you have your own ABI? Good! +; Setting this to 0 will remove the register saving/restoring on +; the stack. All registers then may be trashed. +; Otherwise, d2-d7/a2-a6 are preserved as with the AmigaOS standard. + IFND PRETRACKER_DONT_TRASH_REGS +PRETRACKER_DONT_TRASH_REGS = 1 + ENDC + +; Enable output to copperlist instead of audio registers and DMA wait. +; This gives your slightly more CPU time and less jitter (maybe 7 +; rasterlines). +; +; When enabled, provide a pointer to a copperlist in a1 on calling +; pre_PlayerTick. It will update the necessary fields in the +; copperlist. To initially generate a copperlist (or two), use the +; pre_PrepareCopperlist subroutine. It will write out 37 copper +; commands (WAITs and MOVEs) starting for a given rasterline (if +; you're below rasterline 255, make sure you have the necessary +; wait for this case yourself!). +; +; There are two major reasonable ways to use this: +; - Your intro does no fancy copper shenanigans: +; You can reserve the space of 37 longwords inside your normal +; copperlist. The position should be after rasterline ~35. +; - You do a lot of copper stuff during the frame: +; Create the pretracker copperlist to be at the very end of the +; frame (rasterline 300 is a good spot). Make sure your custom +; copper code has a static jump to the 37 copper instructions +; at its end and terminate the copperlist correctly (hint: +; move.l d1,(a0) after bsr pre_PrepareCopperlist will terminate +; the copperlist ($fffffffe). + IFND PRETRACKER_COPPER_OUTPUT +PRETRACKER_COPPER_OUTPUT = 0 ; 0 = standard CPU wait, 1 = Copperlist + ENDC + +; Pretracker song format description: +; +; $0000 4: PRT ($19 (V0.x), $1b (V1.0), $1e (V1.5)) +; $0004 4: File offset to position data (POSD) +; $0008 4: File offset to pattern data (PATT) +; $000C 4: File offset to instruments (INST) +; $0010 4: File offset to waves (WAVE) +; $0014 20: Songname +; $0028 20: Author +; $003C 1: Restart position for song (<=V1.0) +; $003D 1: Number of patterns (<=V1.0) +; $003E 1: Songlength in patterns (<=V1.0) +; $003F 1: Number of steps per pattern (<=V1.0) +; $0040 1: Number of instruments (<=V1.0), $40 for V1.5 +; $0041 1: Number of waves +; $0042 24: Wave generation ordering (>=V1.0) +; $005a 1: Number of subsongs (>=V1.5) +; [...] +; Position data (POSD): +; - Per subsong (>=V1.5) +; - 1: Restart pos +; - 1: #patterns +; - 1: #numsteps +; - 1: songlength +; - 4: relative pattern offset in pattern data +; - Positions x 4 x [Pattern number (byte), pitch shift (signed byte)] +; +; Pattern data (PATT): +; Each pattern line consists of three bytes: +; - 1 Bit : Bit 4 of Inst Number +; - 1 Bit : ARP instead of effect +; - 6 Bits: Pitch ($01 is C-0, $3d is NOTE OFF) +; +; - 4 Bits: Bit 0-3 of Inst Number +; - 4 Bits: Effect command +; - 8 Bits: Effect data +; - Patterns x steps x 3 bytes +; +; Unknown data after pattern data: (12 10 00 00 00 00) +; +; Instrument definitions (INST): +; - 32 (!) x Null terminated string (or 23 chars max) (for V1.5 this is 64 strings) +; - For each instrument: Instrument Info (ININ) +; - $00 1: Vibrato Delay +; - $01 1: Vibrato Depth +; - $02 1: Vibrato Speed (-1) +; - $03 1: ADSR Attack +; - $04 1: ADSR Decay +; - $05 1: ADSR Sustain +; - $06 1: ADSR Release +; - $07 1: Number of Inst Pattern steps +; +; - For each instrument: +; - 1 Byte: number of steps +; - 3 Bytes x number of steps: Inst Pattern (IPTT) +; +; Inst pattern data (IPTT): +; Each pattern line consists of three bytes: +; - 1 Bit : Next note stitched to this one +; - 1 Bit : Fixed Pitch Note +; - 6 Bits : Pitch ($01 is C-0) +; - 4 Bits : unused? +; - 12 Bits: Effect +; - Patterns x steps x 3 bytes +; +; Wave definitions (WAVE): +; - 24 (!) x Null terminated string (or 23 chars max) +; - Optional padding to even address, if necessary +; - For each wave: +; - 42 Bytes: Wave info structure (see definition below) + +MAX_VOLUME = $40 +MAX_SPEED = $2f +MAX_WAVES = 24 +MAX_INSTRUMENTS = 32 +MAX_TRACK_DELAY = 32 +NOTE_OFF_PITCH = $3d +NOTES_IN_OCTAVE = 12 +NUM_CHANNELS = 4 ; yes, you can reduce the number of channels if you want + +; ---------------------------------------- +; Pattern data +pdb_pitch_ctrl = 0 +pdb_inst_effect = 1 ; for normal pattern data +pdb_effect_cmd = 1 ; for inst pattern +pdb_effect_data = 2 + +; Pattern pos data +ppd_pat_num = 0 +ppd_pat_shift = 1 + +; Instrument Info (ININ) +ii_vibrato_delay = 0 +ii_vibrato_depth = 1 +ii_vibrato_speed = 2 +ii_adsr_attack = 3 +ii_adsr_decay = 4 +ii_adsr_sustain = 5 +ii_adsr_release = 6 +ii_pattern_steps = 7 +ii_SIZEOF = 8 + +; Unpacked Instrument Info (addition to player for faster processing) + rsreset +uii_vibrato_delay rs.w 1 +uii_vibrato_depth rs.w 1 +uii_vibrato_speed rs.w 1 +uii_adsr_release rs.b 1 + rs.b 1 ; dummy +uii_adsr_attack rs.w 1 +uii_adsr_decay rs.w 1 +uii_adsr_sustain rs.w 1 +uii_pattern_steps rs.b 1 + rs.b 1 ; padding +uii_SIZEOF rs.b 0 + + +; MySong offsets + rsreset +sv_waveinfo_table rs.l MAX_WAVES ; 24 pointers to wave infos to avoid mulu +sv_wavelength_table rs.l MAX_WAVES ; 24 longwords to sample lengths (standard octave) (NEW) +sv_wavetotal_table rs.l MAX_WAVES ; 24 longwords to sample lengths for all octaves (NEW) +sv_wavegen_order_table rs.b MAX_WAVES ; 24 bytes +sv_num_waves_b rs.b 1 +sv_num_steps_b rs.b 1 +sv_patterns_ptr rs.l 1 +sv_inst_patterns_table rs.l MAX_INSTRUMENTS ; 32 pointers to pattern data +sv_curr_pat_pos_w rs.w 1 ; only byte used FIXME why is this part of MySong? Should be in Player +sv_pat_pos_len_w rs.w 1 ; only byte used +sv_pat_restart_pos_w rs.w 1 ; only byte used +sv_pos_data_adr rs.l 1 +sv_waveinfo_ptr rs.l 1 ; base pointer of wave info +sv_pattern_table rs.l 256 +sv_inst_infos_table rs.b MAX_INSTRUMENTS*uii_SIZEOF +sv_SIZEOF rs.b 0 + +; ---------------------------------------- +; channel output data (part of pcd structure below) + rsreset +ocd_sam_ptr rs.l 1 ; 0 +ocd_length rs.w 1 ; 4 +ocd_loop_offset rs.w 1 ; 6 +ocd_period rs.w 1 ; 8 +ocd_volume rs.b 1 ; 10 +ocd_trigger rs.b 1 ; 11 needs to be after volume +ocd_unused rs.l 1 ; 12 unused, but makes the structure an even 16 bytes +ocd_SIZEOF rs.b 0 + +; channel structure (part of pv structure) + rsreset +; DO NOT CHANGE ORDER -- OPTIMIZED CLEARING +pcd_pat_portamento_dest_w rs.w 1 ; portamento destination pitch +pcd_pat_pitch_slide_w rs.w 1 + +pcd_pat_vol_ramp_speed_b rs.b 1 +pcd_pat_2nd_inst_num_b rs.b 1 +pcd_pat_2nd_inst_delay_b rs.b 1 +pcd_wave_offset_b rs.b 1 + +pcd_inst_pitch_slide_w rs.w 1 +pcd_inst_sel_arp_note_w rs.w 1 + +pcd_inst_note_pitch_w rs.w 1 +pcd_inst_curr_port_pitch_w rs.w 1 + +pcd_inst_line_ticks_b rs.b 1 +pcd_inst_pitch_pinned_b rs.b 1 +pcd_inst_vol_slide_b rs.b 1 +pcd_inst_step_pos_b rs.b 1 + +pcd_inst_wave_num_w rs.w 1 ; current wave number (1 based) (lower byte used) + +pcd_track_delay_offset_b rs.b 1 ; $ff = no track delay +pcd_inst_speed_stop_b rs.b 1 ; speed byte, $ff stops processing +pcd_inst_pitch_w rs.w 1 + +pcd_inst_vol_w rs.w 1 +pcd_loaded_inst_vol_b rs.b 1 ; low byte only +pcd_pat_vol_b rs.b 1 ; Multiplied with volume of instrument. +; DO NOT CHANGE ORDER -- OPTIMIZED CLEARING END + +pcd_arp_notes_l rs.b 0 +pcd_arp_note_1_b rs.b 1 +pcd_arp_note_2_b rs.b 1 +pcd_arp_note_3_b rs.b 1 + rs.b 1 ; gets cleared + +pcd_last_trigger_pos_w rs.w 1 ; I think this makes sure that we don't retrigger the note on same pos + +pcd_pat_portamento_speed_b rs.b 1 +pcd_pat_adsr_rel_delay_b rs.b 1 ; counts down until adsr release. Seems unused? +pcd_new_inst_num_b rs.b 1 ; load new instrument (number) +pcd_note_off_delay_b rs.b 1 ; time before note is released ($ff = disabled) + +pcd_note_delay_b rs.b 1 ; $ff = no note delay +pcd_track_delay_steps_b rs.b 1 ; $00 = no track delay, $ff = stop track delay (this is for the next channel!) +pcd_track_delay_vol16_b rs.b 1 +pcd_track_init_delay_b rs.b 1 ; number of frames to ignore the delay + +pcd_inst_pattern_steps_b rs.b 1 ; number of steps in instrument pattern + rs.b 1 +pcd_inst_num_w rs.w 1 ; current instrument number (lower byte used) +;pcd_inst_new_step_w rs.w 1 ; seems to be unused +pcd_inst_ping_pong_s_w rs.w 1 ; direction of pingpong (-1 / +1) + +pcd_inst_subloop_wait_w rs.w 1 +pcd_inst_loop_offset_w rs.w 1 +pcd_inst_info_ptr rs.l 1 ; pointer to currently active instrument + +pcd_waveinfo_ptr rs.l 1 ; pointer to currently active waveinfo +pcd_channel_mask_b rs.b 1 +pcd_channel_num_b rs.b 1 +pcd_adsr_phase_w rs.w 1 ; 0=attack, 1=decay, 2=sustain, 3=release +pcd_adsr_volume_w rs.w 1 ; 0 for restart / $400 (word only) +pcd_adsr_phase_speed_b rs.b 1 + rs.b 1 +pcd_adsr_pos_w rs.w 1 ; pos in adsr curve +pcd_adsr_vol64_w rs.w 1 ; some adsr volume + +pcd_vibrato_pos_w rs.w 1 ; +pcd_vibrato_delay_w rs.w 1 ; is a byte value ! do not change order +pcd_vibrato_depth_w rs.w 1 ; is a byte value ! do not change order +pcd_vibrato_speed_w rs.w 1 ; is a byte value ! do not change order +pcd_adsr_release_b rs.b 1 ; is a byte value ! do not change order + rs.b 1 ; padding will be overwritten! + +pcd_out_base rs.b ocd_SIZEOF +pcd_track_delay_buffer rs.b MAX_TRACK_DELAY*ocd_SIZEOF +pcd_SIZEOF rs.b 0 + +pcd_out_ptr_l = pcd_out_base+ocd_sam_ptr +pcd_out_len_w = pcd_out_base+ocd_length +pcd_out_lof_w = pcd_out_base+ocd_loop_offset +pcd_out_per_w = pcd_out_base+ocd_period +pcd_out_vol_b = pcd_out_base+ocd_volume +pcd_out_trg_b = pcd_out_base+ocd_trigger +pcd_out_unused_l = pcd_out_base+ocd_unused ; copied for track delay, but not used? + + rsreset +owb_saw_waves rs.b 128 +owb_sqr_waves rs.b 128 +owb_tri_waves rs.b 128 +owb_wave_length rs.b 1 +owb_SIZEOF rs.b 0 + +; player global variables (not bound to channel) + rsreset +; DO NOT CHANGE ORDER -- OPTIMIZED INIT +pv_pat_curr_row_b rs.b 1 ; current step +pv_next_pat_row_b rs.b 1 +pv_next_pat_pos_b rs.b 1 +pv_pat_speed_b rs.b 1 ; speed byte (unfiltered) +; DO NOT CHANGE ORDER -- OPTIMIZED INIT END + +pv_pat_stopped_b rs.b 1 ; 0 = stop, 1 = run +pv_pat_line_ticks_b rs.b 1 +pv_loop_pattern_b rs.b 1 ; repeat current pattern, do not advance +pv_songend_detected_b rs.b 1 + +pv_trigger_mask_w rs.w 1 + +pv_my_song rs.l 1 +pv_sample_buffer_ptr rs.l 1 ; pointer to start of sample buffer +pv_copperlist_ptr rs.l 1 +pv_wave_sample_table rs.l MAX_WAVES ; 24 pointers to sample starts +pv_period_table rs.w 16*NOTES_IN_OCTAVE*3 +pv_channeldata rs.b NUM_CHANNELS*pcd_SIZEOF + IFNE PRETRACKER_VOLUME_TABLE +pv_osc_buffers rs.b 0 +pv_volume_table rs.b (MAX_VOLUME+1)*MAX_VOLUME*2 + ELSE +pv_osc_buffers rs.b NOTES_IN_OCTAVE*owb_SIZEOF + ENDC + +pv_precalc_sample_size rs.l 1 +pv_precalc_progress_ptr rs.l 1 +pv_wg_wave_ord_num_w rs.w 1 + IFNE PRETRACKER_PARANOIA_MODE ; same wave for mixing cannot be selected in Pretracker +pv_wg_curr_wave_num_b rs.b 1 + rs.b 1 + ENDC +pv_wg_curr_sample_ptr rs.l 1 +pv_wg_curr_samend_ptr rs.l 1 +pv_wg_curr_sample_len_w rs.w 1 +pv_wg_chord_note_num_b rs.b 1 ; don't change order +pv_wg_unisono_run_b rs.b 1 ; don't change order +pv_wg_chord_flag_w rs.w 1 +pv_wg_chord_pitches rs.l 1 +pv_wg_osc_speed_l rs.l 1 +pv_wg_flt_taps rs.w 4 +pv_SIZEOF rs.b 0 + +; waveinfo $2a bytes +wi_loop_start_w = $00 +wi_loop_end_w = $02 +wi_subloop_len_w = $04 +wi_allow_9xx_b = $06 +wi_subloop_wait_b = $07 +wi_subloop_step_w = $08 +wi_chipram_w = $0a +wi_loop_offset_w = $0c +wi_chord_note1_b = $0e +wi_chord_note2_b = $0f +wi_chord_note3_b = $10 +wi_chord_shift_b = $11 +wi_osc_unknown_b = $12 ; always $00? (unused in code?) +wi_osc_phase_spd_b = $13 +wi_flags_b = $14 ; bit 0/1: osc type, bit 2: needs extra octaves, bit 3: boost, bit 4: pitch linear, bit 5: vol fast +wi_osc_phase_min_b = $15 +wi_osc_phase_max_b = $16 +wi_osc_basenote_b = $17 +wi_osc_gain_b = $18 +wi_sam_len_b = $19 ; in multiples of 128, zero-based (0 == 128) +wi_mix_wave_b = $1a +wi_vol_attack_b = $1b +wi_vol_delay_b = $1c +wi_vol_decay_b = $1d +wi_vol_sustain_b = $1e +wi_flt_type_b = $1f ; 1=lowpass, 2=highpass, 3=bandpass, 4=notch +wi_flt_resonance_b = $20 +wi_pitch_ramp_b = $21 +wi_flt_start_b = $22 +wi_flt_min_b = $23 +wi_flt_max_b = $24 +wi_flt_speed_b = $25 +wi_mod_params_l = $26 +wi_mod_wetness_b = $26 +wi_mod_length_b = $27 +wi_mod_predelay_b = $28 +wi_mod_density_b = $29 ; (1-7), unisono (bits 3/4) and post bit 5 +wi_SIZEOF = $2a + +; LSP has a byte stream and a word stream: +; - there is a control byte, which can be 0, to allow additional control outputs. +; - the control values go through an indirection table for reasonable combinations +; - the bits 4- 7 tell if the byte stream contains new volumes +; - the bits 0- 3 tell if the word stream contains new periods (if the bits are all zero, this is skipped) +; - the bits 15- 8 come in pairs: +; - 11=SetIns+Reset (take inst offset from word stream, load ptr/len, stop DMA, set reset pos inst for loop) +; - 10=SetIns+NoReset (take inst offset from word stream, load ptr/len, set reset pos inst for loop) +; - 01=Load new adr/len (set loop) +; +; what would we need for a Pretracker capable LSP-like player? +; - base instrument -> byte (5 bit) +; - offset sequence -> byte +; - loop len -> byte +; - period -> word +; - volume -> byte +; - trigger -> bit +; + + include "../includes/hardware/custom.i" + include "../includes/hardware/dmabits.i" + +CLIPTO8BIT MACRO + cmpi.w #-$80,\1 + bge.s .nominclip\@ + moveq.l #-$80,\1 +.nominclip\@ + cmpi.w #$7F,\1 + ble.s .nomaxclip\@ + moveq.l #$7F,\1 +.nomaxclip\@ + ENDM + +CLIPORTRUNC8BIT MACRO + beq.s .unboosted\@ + asr.l #6,\1 + cmpi.w #-$80,\1 + bge.s .nominclip\@ + moveq.l #-$80,\1 +.nominclip\@ + cmpi.w #$7F,\1 + ble.s .nomaxclip\@ + moveq.l #$7F,\1 + bra.s .nomaxclip\@ +.unboosted\@ + asr.l #8,\1 +.nomaxclip\@ + ENDM + +CLIPTO8BITAFTERADD MACRO + bvc.s .noclip\@ + spl \1 + eor.b #$7f,\1 +.noclip\@ + ENDM + + IFNE PRETRACKER_KEEP_JUMP_TABLE +pre_FuncTable + dc.l pre_SongInit-pre_FuncTable + dc.l pre_PlayerInit-pre_FuncTable + dc.l pre_PlayerTick-pre_FuncTable + ENDC + ;dc.b '$VER: Raspberry Casket 1.0',0 + ;even + + IFNE PRETRACKER_COPPER_OUTPUT +;******************************************************************** +;-------------------------------------------------------------------- +; pre_PrepareCopperlist - initialize copperlist for replaying +; +; a0.l = copperlist (37 longwords for 4 channels, 5+8*NUM_CHANNELS) +; d0.w = rasterline (<239 or >=256) +; out: a0 = copperlist ptr after init +;******************************************************************** +pre_PrepareCopperlist: + IFNE PRETRACKER_DONT_TRASH_REGS + movem.l d2-d3/d6/d7,-(sp) + ENDC + moveq.l #-2,d1 + lsl.w #8,d0 + move.b #$07,d0 + move.w d0,(a0)+ + move.w d1,(a0)+ + + move.l #(dmacon<<16)|DMAF_AUDIO,(a0)+ + + add.w #$500,d0 + move.w d0,(a0)+ + move.w d1,(a0)+ + + ; writing 5*4 = 20 words + move.w #aud0+ac_ptr,d2 + moveq.l #0,d3 + moveq.l #NUM_CHANNELS-1,d7 +.chloop moveq.l #5-1,d6 +.dloop move.w d2,(a0)+ + move.w d3,(a0)+ + addq.w #2,d2 + dbra d6,.dloop + addq.w #ac_SIZEOF-ac_dat,d2 + dbra d7,.chloop + + move.l #(dmacon<<16)|DMAF_SETCLR,(a0)+ + + add.w #$500,d0 + move.w d0,(a0)+ + move.w d1,(a0)+ + + ; writing 2*4 = 12 words + move.w #aud0+ac_ptr,d2 + moveq.l #NUM_CHANNELS-1,d7 +.chloop2 + moveq.l #3-1,d6 +.dloop2 move.w d2,(a0)+ + move.w d3,(a0)+ + addq.w #2,d2 + dbra d6,.dloop2 + add.w #ac_SIZEOF-ac_per,d2 + dbra d7,.chloop2 + IFNE PRETRACKER_DONT_TRASH_REGS + movem.l (sp)+,d2-d3/d6/d7 + ENDC + rts + + ENDC + +;******************************************************************** +;-------------------------------------------------------------------- +; SongInit - initialize data structure belonging to a song +; +; In: +; - a0: MyPlayer structure (unused) +; - a1: MySong structure (must be sv_SIZEOF bytes!) +; - a2: Pretracker song data +; Out: +; - d0: chipmemory (bytes) required for samples or 0 on error +;******************************************************************** +pre_SongInit: + IFNE PRETRACKER_DONT_TRASH_REGS + movem.l d2/d7/a2-a5,-(sp) + ENDC + moveq.l #0,d0 + move.l $0000(a2),d1 + move.b d1,d2 + clr.b d1 + cmpi.l #$50525400,d1 ; "PRE"-Text + bne .error + moveq.l #MAX_INSTRUMENTS-1,d7 ; notice there's one extra name (available in 1.5, but not usable)! + IFNE PRETRACKER_SUPPORT_V1_5 + cmpi.b #$1e,d2 + bgt .error + bne.s .nopatchv15 + move.l $005c(a2),d0 ; make song backward compatible + ror.w #8,d0 + move.l d0,$003c(a2) + addq.l #8,$0004(a2) ; skip over first pattern data + moveq.l #2*MAX_INSTRUMENTS-1,d7 ; v1.5 has 32 slots (the other ones used for sfx) +.nopatchv15 + ELSE + cmpi.b #$1b,d2 + bgt .error + ENDC + + move.l a1,a0 + move.w #sv_SIZEOF,d0 + bsr pre_MemClr + + move.b $003c(a2),sv_pat_restart_pos_w+1(a1) ; song restart pos + move.b $003e(a2),sv_pat_pos_len_w+1(a1) ; songlength in pattern positions + move.b $003f(a2),sv_num_steps_b(a1) ; number of steps! + move.b $0041(a2),sv_num_waves_b(a1) ; number of instruments + + move.l $0004(a2),d0 + add.l a2,d0 + move.l d0,sv_pos_data_adr(a1) ; address to position data (POSD) + + move.l $0008(a2),d0 + add.l a2,d0 + move.l d0,sv_patterns_ptr(a1) ; address to pattern data (PATT) + + move.l $000c(a2),d0 ; offset into instrument names + lea (a2,d0.l),a0 ; instrument names + +.instrnamesloop + moveq.l #23-1,d0 ; max 23 chars +.inststrloop + tst.b (a0)+ + dbeq d0,.inststrloop + dbra d7,.instrnamesloop + + moveq.l #0,d7 + move.b $0040(a2),d7 ; number of instruments + IFNE PRETRACKER_PARANOIA_MODE + beq.s .noinstsskip + ENDC + move.l d7,d0 + lsl.w #3,d0 + add.l a0,d0 ; skip 8 bytes of info per instrument (ININ) + lea sv_inst_patterns_table(a1),a3 + lea sv_inst_infos_table(a1),a4 + IFNE PRETRACKER_SUPPORT_V1_5 + cmp.w #MAX_INSTRUMENTS,d7 + ble.s .notruncto32 + moveq.l #MAX_INSTRUMENTS,d7 +.notruncto32 + ENDC + subq.w #1,d7 +.instinfoloop + move.l d0,(a3)+ + + moveq.l #0,d1 + move.b (a0)+,d1 ; ii_vibrato_delay + lea pre_vib_delay_table(pc),a5 + move.b (a5,d1.w),d1 + addq.w #1,d1 + move.w d1,uii_vibrato_delay(a4) + + moveq.l #0,d1 + move.b (a0)+,d1 ; ii_vibrato_depth + move.b pre_vib_depth_table-pre_vib_delay_table(a5,d1.w),uii_vibrato_depth+1(a4) + + move.b (a0)+,d1 ; ii_vibrato_speed + move.b pre_vib_speed_table-pre_vib_delay_table(a5,d1.w),uii_vibrato_speed+1(a4) + + move.b (a0)+,d1 ; ii_adsr_attack + add.w d1,d1 + lea pre_fast_roll_off_16(pc),a5 + move.w (a5,d1.w),d1 + move.w d1,uii_adsr_attack(a4) + + moveq.l #0,d1 + move.b (a0)+,d1 ; ii_adsr_decay + lea pre_ramp_up_16(pc),a5 + move.b (a5,d1.w),uii_adsr_decay+1(a4) + + move.b (a0)+,d1 ; ii_adsr_sustain + ; what is this? a patch? + cmp.b #15,d1 + bne.s .dont_patch_sustain + moveq.l #16,d1 +.dont_patch_sustain + lsl.w #6,d1 + move.w d1,uii_adsr_sustain(a4) + + moveq.l #0,d1 + move.b (a0)+,d1 ; ii_adsr_release + lea (pre_ramp_up_16,pc),a5 + move.b (a5,d1.w),uii_adsr_release(a4) + + move.b (a0)+,d1 ; ii_pattern_steps + move.b d1,uii_pattern_steps(a4) + add.l d1,d0 + add.l d1,d0 + add.l d1,d0 ; calc next start address + lea uii_SIZEOF(a4),a4 + dbra d7,.instinfoloop + +.noinstsskip + move.l $0010(a2),d0 ; offset into wave names + lea (a2,d0.l),a0 + moveq.l #MAX_WAVES-1,d7 +.wavenamesloop + moveq.l #23-1,d0 ; max 23 chars +.wavestrloop + tst.b (a0)+ + dbeq d0,.wavestrloop + dbra d7,.wavenamesloop + + move.l a0,d0 + lsr.w #1,d0 + bcc.s .addressiseven + addq.l #1,a0 ; make address even +.addressiseven + move.l a0,sv_waveinfo_ptr(a1) + + lea sv_wavegen_order_table(a1),a0 + cmpi.b #$19,d2 ; check if version is higher than 19 + bhi.s .haswaveorderinfo + + moveq.l #0,d0 ; fill 24 bytes with default order of waves? + moveq.l #MAX_WAVES-1,d7 +.fillcount + move.b d0,(a0)+ + addq.b #1,d0 + dbra d7,.fillcount + bra.s .contafterworkaround + +.haswaveorderinfo + moveq.l #(MAX_WAVES/4)-1,d7 + lea $0042(a2),a2 ; offset into wave ordering +.memcpyloop + move.l (a2)+,(a0)+ + dbra d7,.memcpyloop + +.contafterworkaround + moveq.l #2,d0 ; at least empty sample + moveq.l #0,d7 + move.b sv_num_waves_b(a1),d7 ; has instruments? + IFNE PRETRACKER_PARANOIA_MODE + beq.s .hasnoinstruments + ENDC + + move.l sv_waveinfo_ptr(a1),a3 + subq.w #1,d7 +.wavetableloop + moveq.l #0,d1 + move.b wi_sam_len_b(a3),d1 + addq.w #1,d1 + lsl.w #7,d1 + move.l d1,sv_wavelength_table-sv_waveinfo_table(a1) + btst #2,wi_flags_b(a3) + beq.s .onlythreeocts + mulu #15,d1 + lsr.l #3,d1 ; * 1.875 +.onlythreeocts + move.l d1,sv_wavetotal_table-sv_waveinfo_table(a1) + move.l a3,(a1)+ + add.l d1,d0 + lea wi_SIZEOF(a3),a3 + dbra d7,.wavetableloop + ; d0 will contain the size of the samples +.hasnoinstruments +.error +.exit + IFNE PRETRACKER_DONT_TRASH_REGS + movem.l (sp)+,d2/d7/a2-a5 + ENDC + rts + +;******************************************************************** +;-------------------------------------------------------------------- +; PlayerInit - initialize player and calculate samples +; +; In: +; - a0: MyPlayer (must have size of pv_SIZEOF, will be initialized) +; - a1: sample buffer +; - a2: MySong (must have been filled with SongInit before!) +; - a3: pointer to a longword for the progress of samples bytes generated (or null) +;******************************************************************** +pre_PlayerInit: + IFNE PRETRACKER_DONT_TRASH_REGS + movem.l d2-d7/a2-a6,-(sp) + ENDC + move.l a0,a4 + move.l a2,a6 + + move.w #pv_SIZEOF,d0 + bsr pre_MemClr ; keeps a1 unchanged! + +; ---------------------------------------- +; proposed register assignment: +; a0 = sample output / scratch +; a1 = scratch +; a3 = waveinfo +; a4 = MyPlayer +; a6 = MySong + + move.l a2,pv_my_song(a4) + IFNE PRETRACKER_PROGRESS_SUPPORT + move.l a3,pv_precalc_progress_ptr(a4) + ENDC + + move.l a1,pv_sample_buffer_ptr(a4) + IFNE PRETRACKER_PARANOIA_MODE + beq.s .hasnosamplebuffer ; PARANOIA + ENDC + + clr.w (a1)+ ; empty sample + moveq.l #0,d7 + move.b sv_num_waves_b(a6),d7 + IFNE PRETRACKER_PARANOIA_MODE + beq.s .hasnosamplebuffer ; PARANOIA + ENDC + + lea pv_wave_sample_table(a4),a0 + lea sv_wavetotal_table(a6),a3 + subq.w #1,d7 +.samplestartsloop + move.l a1,(a0)+ ; write sample start pointer + adda.l (a3)+,a1 + dbra d7,.samplestartsloop +.hasnosamplebuffer + +; ---------------------------------------- + + lea pre_period_table(pc),a0 + lea pv_period_table(a4),a1 + +.calcperiodtable + ; fill the missing entries in the period table by interpolating + moveq.l #3*NOTES_IN_OCTAVE-1,d7 +.periodtableloop + move.w (a0)+,d0 + move.w (a0),d1 + sub.w d0,d1 + swap d0 + clr.w d0 + swap d1 + clr.w d1 + asr.l #4,d1 + + moveq.l #16-1,d6 +.perfineipolloop + swap d0 + move.w d0,(a1)+ + swap d0 + add.l d1,d0 + dbra d6,.perfineipolloop + dbra d7,.periodtableloop + +; ---------------------------------------- + + moveq.l #0,d0 + move.b sv_num_steps_b(a6),d0 + move.w d0,d1 + add.w d0,d0 + add.w d1,d0 ; *3 bytes per pattern line + + move.l sv_patterns_ptr(a6),a3 + lea sv_pattern_table(a6),a0 + move.w #255-1,d7 ; FIXME we should use the number of patterns instead? +.pattableloop + move.l a3,(a0)+ + add.w d0,a3 + dbra d7,.pattableloop + +; ---------------------------------------- + + move.l #$00ffff06,pv_pat_curr_row_b(a4) ; pattern frame = 0, line = $ff, pattern pos = $ff, speed = 6 + move.b #1,pv_pat_stopped_b(a4) ; start pattern processing + + bsr pre_update_pat_line_counter + + move.l sv_waveinfo_ptr(a6),a1 + lea pv_channeldata(a4),a0 + moveq.l #NUM_CHANNELS-1,d7 + moveq.l #0,d0 +.chaninitloop2 + move.b #MAX_VOLUME,pcd_pat_vol_b(a0) + st pcd_track_delay_offset_b(a0) + move.l a1,pcd_waveinfo_ptr(a0) + move.w #3,pcd_adsr_phase_w(a0) + + move.l pv_sample_buffer_ptr(a4),pcd_out_ptr_l(a0) + move.w #2,pcd_out_len_w(a0) + move.w #$7B,pcd_out_per_w(a0) + move.b d0,pcd_channel_num_b(a0) + bset d0,pcd_channel_mask_b(a0) + addq.b #1,d0 + lea pcd_SIZEOF(a0),a0 + dbra d7,.chaninitloop2 + +; ---------------------------------------- + + lea pre_log12_table(pc),a0 ; 128, 121, 114, 107, 102, 96, 90, 85, 80, 76, 72, 67 + lea pv_osc_buffers+owb_sqr_waves(a4),a1 + moveq.l #NOTES_IN_OCTAVE-1,d7 +.noteloop + moveq.l #0,d6 + move.l d6,a3 ; tabpos + move.b (a0)+,d6 ; period + move.b d6,owb_wave_length-owb_sqr_waves(a1) + + move.l #$ff00,d5 + divu d6,d5 ; frac increment + + move.w d6,d4 + lsr.w #1,d4 ; half-period + move.w d4,d3 + lsr.w #1,d3 ; quarter-period + + moveq.l #0,d0 ; acc + lea (a1,d6.w),a2 + lea owb_tri_waves-owb_sqr_waves(a2),a2 + suba.w d3,a2 +.notewaveloop + move.w d0,d2 + lsr.w #8,d2 + + moveq.l #$7f,d1 + sub.b d2,d1 + move.b d1,owb_saw_waves-owb_sqr_waves(a1,a3.w) + + add.b d2,d2 + cmp.w a3,d3 ; tabpos == negquarter + bne.s .nowrapback + suba.w d6,a2 ; go back to start of period +.nowrapback + cmp.w d0,a3 + ble.s .otherhalf + moveq.l #$7f,d1 + sub.b d2,d1 + move.b d1,(a2)+ + bra.s .clip80 + +.otherhalf + add.b #$80,d2 + move.b d2,(a2)+ + moveq.l #$7f,d2 + cmp.w a3,d4 + bne.s .noclip80 +.clip80 moveq.l #-$80,d2 +.noclip80 + move.b d2,owb_sqr_waves-owb_sqr_waves(a1,a3.w) + + add.w d5,d0 ; increment acc by frac + addq.w #1,a3 ; increment pos + + cmp.w a3,d6 + bne.s .notewaveloop + + lea owb_SIZEOF(a1),a1 + dbra d7,.noteloop + +; ---------------------------------------- + +.audioinit + bset #1,$BFE001 ; filter off + + IFNE PRETRACKER_PARANOIA_MODE + tst.b sv_num_waves_b(a6) + beq .earlyexit ; PARANOIA + ENDC + +; ---------------------------------------- +; proposed register assignment: +; a0 = sample output +; a1 = scratch +; a3 = songinfo +; a4 = MyPlayer +; a6 = MySong / waveinfo + +.wavegenloop + ;movea.l pv_my_song(a4),a6 + lea sv_wavegen_order_table(a6),a1 + move.w pv_wg_wave_ord_num_w(a4),d0 ; counter through all 24 waves + moveq.l #0,d1 + move.b (a1,d0.w),d1 ; apply wave order redirection + IFNE PRETRACKER_PARANOIA_MODE ; same wave for mixing cannot be selected in Pretracker + move.b d1,pv_wg_curr_wave_num_b(a4) + ENDC + lsl.w #2,d1 + lea sv_wavelength_table(a6,d1.w),a6 + move.l sv_wavelength_table-sv_wavelength_table(a6),d0 + move.w d0,pv_wg_curr_sample_len_w(a4) + IFNE PRETRACKER_PROGRESS_SUPPORT + move.l sv_wavetotal_table-sv_wavelength_table(a6),pv_precalc_sample_size(a4) + ENDC + move.l sv_waveinfo_table-sv_wavelength_table(a6),a3 + + move.l pv_wave_sample_table(a4,d1.w),a0 + move.l a0,pv_wg_curr_sample_ptr(a4) + + ; clear sample data (a0 and d0 from above) + bsr pre_MemClr + move.l a0,pv_wg_curr_samend_ptr(a4) + + ; read out chord information + lea wi_chord_note1_b(a3),a1 + move.b (a1)+,d1 + move.b (a1)+,d2 + move.b (a1)+,d3 + + moveq.l #0,d4 + move.b d1,d4 + or.b d2,d4 + or.b d3,d4 + seq d4 + neg.b d4 + move.w d4,pv_wg_chord_flag_w(a4) ; has chord flag (0/1) + + move.b wi_osc_basenote_b(a3),d0 + add.b d0,d1 + add.b d0,d2 + add.b d0,d3 + lea pv_wg_chord_pitches(a4),a1 + move.b d0,(a1)+ + move.b d1,(a1)+ + move.b d2,(a1)+ + move.b d3,(a1)+ + + suba.l a5,a5 + clr.w pv_wg_chord_note_num_b(a4) ; and pv_wg_chord_note_num_b + +.wavegen_chordloop + lea pv_wg_chord_pitches(a4),a1 + moveq.l #0,d1 + move.b pv_wg_chord_note_num_b(a4),d1 ; chord note counter + move.b (a1,d1.w),d0 ; get chord note + ext.w d0 + + tst.w d1 + beq.s .base_note_is_never_skipped ; is base note? + cmp.b wi_osc_basenote_b(a3),d0 + beq .wave_gen_tone_done ; skip chord notes that are same as base note +.base_note_is_never_skipped + moveq.l #0,d1 + moveq.l #NOTES_IN_OCTAVE,d2 + move.w d0,d1 + move.w d0,a2 ; save base note, used later (much later, noise generator)! + add.w #NOTES_IN_OCTAVE*NOTES_IN_OCTAVE,d1 ; make sure we don't run into negative modulo + divu d2,d1 + swap d1 + move.w d1,d0 ; note within octave + swap d1 + sub.w d2,d1 ; restore octave + + mulu #owb_SIZEOF,d0 + lea (a4,d0.w),a1 + + lea pv_osc_buffers+owb_saw_waves(a1),a6 + moveq.l #3,d0 + and.b wi_flags_b(a3),d0 + beq.s .osc_selected + lea owb_tri_waves-owb_saw_waves(a6),a6 + subq.b #1,d0 + beq.s .osc_selected + lea owb_sqr_waves-owb_tri_waves(a6),a6 + subq.b #1,d0 + beq.s .osc_selected + suba.l a6,a6 ; noise selected +.osc_selected + + move.l #$8000,d6 + move.w d1,d0 ; check octave shift + bgt.s .shiftleft + beq.s .contshift +;.shiftright + move.w d0,d3 + neg.w d3 + asr.l d3,d6 + bra.s .contshift +.shiftleft + lsl.l d0,d6 +.contshift + +; ---------------------------------------- +; pitch ramp + move.b wi_pitch_ramp_b(a3),d3 + ext.w d3 + ext.l d3 + btst #4,wi_flags_b(a3) ; pitch linear flag + beq.s .pitch_not_linear + tst.b d3 + bgt.s .pitch_ramp_positive + + lsl.l d0,d3 + add.l d3,d3 + bra.s .pitch_ramp_cont + +.pitch_not_linear + tst.b d3 + ble.s .pitch_ramp_cont +.pitch_ramp_positive + muls d3,d3 +.pitch_ramp_cont + move.l d3,d2 + lsl.l #8,d2 + lsl.l #2,d2 + + moveq.l #0,d7 + move.b pv_osc_buffers+owb_wave_length(a1),d7 ; get period + moveq.l #15,d5 + lsl.l d5,d7 + + sub.w d0,d5 ; 15-octave + lsl.w #3,d5 + + moveq.l #0,d3 + move.b wi_osc_phase_min_b(a3),d3 + + mulu d5,d3 + lsl.l #6,d3 + + moveq.l #0,d0 + move.b wi_osc_phase_max_b(a3),d0 + mulu d5,d0 + lsl.l #6,d0 + move.l d0,a5 + + moveq.l #0,d5 + move.b wi_osc_phase_spd_b(a3),d5 + lsl.l #8,d5 + lsl.l #3,d5 + + cmp.l d3,d0 + bge.s .osc_with_positive_phase_speed + neg.l d5 + + movea.l d3,a5 + bra.s .osc_continue +.osc_with_positive_phase_speed + move.l d3,d0 + +.osc_continue + move.l d0,pv_wg_osc_speed_l(a4) + + ; d0 = d6 * chord_shift * chordnum + d6 * phase_min = d6 * (chord_shift * chordnum + phase_min) + + moveq.l #0,d4 + move.b wi_chord_shift_b(a3),d4 + move.w pv_wg_chord_flag_w(a4),d0 + add.b pv_wg_chord_note_num_b(a4),d0 + mulu d0,d4 + moveq.l #0,d0 + move.b wi_osc_phase_min_b(a3),d0 + add.w d0,d4 + move.l d6,d0 + lsr.l #4,d0 + lsl.l #4,d4 + mulu d4,d0 + + cmp.l d7,d0 + ble.s .lbC002516 +.lbC002510 + sub.l d7,d0 + cmp.l d7,d0 + bgt.s .lbC002510 +.lbC002516 + move.l a6,d4 + bne .no_noise + +; ---------------------------------------- +; d1 = octave +; d5 = osc phase speed +; a2 = base note +.gen_noise + IFNE PRETRACKER_PARANOIA_MODE + tst.w pv_wg_curr_sample_len_w(a4) + beq .wave_gen_tone_done + ENDC + + move.l #$8000,d5 + move.l d5,a5 + tst.w d1 + bge.s .gen_noise_positive_octave + +.gen_noise_negative_octave + moveq.l #NOTES_IN_OCTAVE,d1 + move.l a2,d3 + neg.l d3 + move.l d3,d0 + divu d1,d0 + IFNE PRETRACKER_PARANOIA_MODE + bvs.s .divisionoverflow + ENDC + addq.w #1,d0 + lsr.w d0,d5 + moveq.l #0,d0 + move.w d5,d0 + divu d1,d0 + moveq.l #0,d4 + move.w d0,d4 + IFNE PRETRACKER_PARANOIA_MODE + bra.s .returnfromoverflow +.divisionoverflow + move.l #$AAA,d4 ; some dummy value, I would expect +.returnfromoverflow + ENDC + moveq.l #0,d0 + move.w d3,d0 +.cheap_mod12 + sub.w d1,d0 + bpl.s .cheap_mod12 + neg.w d0 + mulu d4,d0 + add.l d0,d5 + +.gen_noise_positive_octave + moveq.l #0,d0 + move.b wi_osc_phase_min_b(a3),d0 + moveq.l #0,d1 + move.b wi_chord_shift_b(a3),d1 + add.w d1,d0 + addq.w #1,d0 + + movea.l d5,a1 + movea.l pv_wg_curr_sample_ptr(a4),a0 + moveq.l #0,d1 + moveq.l #0,d6 + moveq.l #0,d3 + move.b wi_osc_gain_b(a3),d3 + +.gen_noise_outerloop + move.w d0,d1 ; random noise generator + lsl.w #8,d1 + lsl.w #5,d1 + eor.w d1,d0 + + move.w d0,d1 + lsr.w #8,d1 + lsr.w #1,d1 + eor.w d1,d0 + + move.w d0,d1 + lsl.w #7,d1 + eor.w d1,d0 + + cmpa.l #$8000,a5 ; if symmetrical + beq.s .gen_noise_centered + ; what does this do? (a5 - $8000) (a5 +$7fff)&$8000 + move.l a5,d4 + addi.l #$FFFF8000,d4 + move.l a5,d1 + addi.l #$FFFF7FFF,d1 + andi.w #$8000,d1 + movea.l d4,a5 + suba.l d1,a5 +.gen_noise_centered + + move.b d0,d1 + ext.w d1 + move.w d3,d4 + muls d1,d4 + move.l d4,d1 + asr.l #7,d1 + CLIPTO8BIT d1 + add.b (a0),d1 + +.gen_noise_innerloop + move.b d1,(a0)+ + adda.l a1,a5 + tst.l d2 + beq.s .lbC002BAC + add.l d2,d6 + move.l d6,d4 + asr.l #8,d4 + asr.l #2,d4 + add.l d5,d4 + movea.l d4,a1 + + btst #4,wi_flags_b(a3) ; pitch linear flag + beq.s .noise_nonlinear_pitch + move.l d2,d4 + asr.l #7,d4 + sub.l d4,d2 +.noise_nonlinear_pitch + + cmpa.w #$1FF,a1 + bgt.s .lbC002BAC + moveq.l #0,d2 + move.l d2,a5 + ;suba.l a5,a5 + movea.w #$200,a1 +.lbC002BAC + cmpa.l pv_wg_curr_samend_ptr(a4),a0 + beq .wave_gen_tone_done + cmpa.w #$7FFF,a5 + ble.s .gen_noise_innerloop + bra .gen_noise_outerloop + +.no_noise + move.l d6,d1 + tst.b pv_wg_unisono_run_b(a4) + beq.s .is_not_in_unisono + + moveq.l #3<<3,d1 + and.b wi_mod_density_b(a3),d1 + lsr.b #3,d1 + moveq.l #9,d4 + sub.b d1,d4 + + move.l d6,d1 + asr.l d4,d1 + add.l d6,d1 +.is_not_in_unisono + + IFNE PRETRACKER_PARANOIA_MODE + tst.w pv_wg_curr_sample_len_w(a4) + beq .wave_gen_tone_done + ENDC + +; ---------------------------------------- +; chord gen +; in: d0/d1/d2/d3/d5/d7 +; in: a0 + move.l d3,a1 + movea.l pv_wg_curr_sample_ptr(a4),a0 + suba.l a2,a2 + +.chordtoneloop + move.l d0,d4 + sub.l a1,d4 + bpl.s .noclip_osc_phase + moveq.l #0,d4 +.noclip_osc_phase + asr.l #8,d4 + asr.l #7,d4 + move.b (a6,d4.w),d4 ; fetch precalced sample + ext.w d4 + + moveq.l #0,d3 + move.b wi_osc_gain_b(a3),d3 + muls d4,d3 + asr.w #7,d3 + + move.b (a0),d4 + ext.w d4 + add.w d3,d4 + CLIPTO8BIT d4 + move.b d4,(a0)+ + + add.l d1,d0 + cmp.l d7,d0 + blt.s .lbC0025A2 + sub.l d7,d0 + add.l d5,a1 + cmp.l a5,a1 + blt.s .lbC00259A + neg.l d5 + move.l a5,a1 +.lbC00259A + cmp.l pv_wg_osc_speed_l(a4),a1 + bgt.s .lbC0025A2 + neg.l d5 + move.l pv_wg_osc_speed_l(a4),a1 +.lbC0025A2 + tst.l d2 + beq.s .chordtone_done + adda.l d2,a2 + move.l a2,d1 + asr.l #8,d1 + asr.l #2,d1 + add.l d6,d1 + + btst #4,wi_flags_b(a3) ; pitch linear flag + beq.s .no_linear_pitch + move.l d2,d4 + asr.l #7,d4 + sub.l d4,d2 +.no_linear_pitch + cmp.l d7,d1 + bcs.s .chordtone_done + moveq.l #0,d2 + moveq.l #0,d1 +.chordtone_done + cmpa.l pv_wg_curr_samend_ptr(a4),a0 + bne.s .chordtoneloop + +.wave_gen_tone_done + addq.b #1,pv_wg_chord_note_num_b(a4) + cmp.b #4,pv_wg_chord_note_num_b(a4) + bne .wavegen_chordloop + + moveq.l #3<<3,d0 + and.b wi_mod_density_b(a3),d0 ; unisono + beq.s .chords_done + move.l a6,d1 + beq.s .chords_done + tst.b pv_wg_unisono_run_b(a4) + bne.s .chords_done + move.w #$0001,pv_wg_chord_note_num_b(a4) ; sets also pv_wg_unisono_run_b + bra .wavegen_chordloop + +.chords_done +; ---------------------------------------- +; filters +; proposed register assignment: +; a0 = sample output +; a1 = end of filter chunk +; a2 = filter func +; d7/a6 = filter start +; a4 = MyPlayer +; a5 = unused +; a3 = waveinfo +; d3/d4/d5/d6 = filter taps +; d0/d1/d7 = scratch + + moveq.l #0,d0 + move.b wi_flt_type_b(a3),d0 + beq .filter_done + + IFNE PRETRACKER_PARANOIA_MODE + tst.w pv_wg_curr_sample_len_w(a4) + beq .filter_done + ENDC + + add.w d0,d0 + lea .filterfunc_jmptable(pc),a2 + add.w -1*2(a2,d0.w),a2 + + moveq.l #0,d4 ; filter tap values + moveq.l #0,d5 ; filter tap values + movem.l d4-d5,pv_wg_flt_taps(a4) + + lea wi_flt_start_b(a3),a0 + moveq.l #0,d0 + move.b (a0)+,d0 ; wi_flt_start_b + lsl.w #8,d0 + + move.b (a0)+,d4 ; wi_flt_min_b + lsl.w #8,d4 ; flt_min*256 + + move.b (a0)+,d5 ; wi_flt_max_b + lsl.w #8,d5 ; flt_max*256 + + move.b (a0)+,d3 ; wi_flt_speed_b + ext.w d3 + ext.l d3 ; flt_speed*128 + lsl.l #7,d3 + + movea.l pv_wg_curr_sample_ptr(a4),a0 + +.entry_to_filter_loop + move.l d0,a6 + move.l d3,d1 ; flt_speed_b*128 + adda.l d1,a6 ; suppress M68kUnexpectedConditionalInstruction + bgt.s .filter_speed_pos + +.filter_speed_neg + move.l d4,d1 ; flt_min*256 + cmp.l d1,d0 + blt.s .lbC002790 + cmp.l d1,a6 + bgt.s .lbC002936 + move.l d1,a6 + cmp.l d5,d1 ; flt_max*256 + beq.s .filter_load_min + neg.l d3 ; flt_speed_b*128 + bra.s .filter_load_min + +.filterfunc_jmptable + dc.w .lowpassfilter-.filterfunc_jmptable + dc.w .highpassfilter-.filterfunc_jmptable + dc.w .bandpassfilter-.filterfunc_jmptable + dc.w .notchfilter-.filterfunc_jmptable + +.lbC002790 + tst.l d0 + blt.s .lbC002936 + move.l a6,d7 + bgt.s .lbC002936 + neg.l d3 ; flt_speed_b*128 + move.w #$FF,d2 + move.w d2,d1 + sub.l a6,a6 + bra.s .filter_cont + +.filter_speed_pos + cmp.l d5,d0 ; flt_max*256 + bgt.s .lbC002D2A + cmp.l d5,a6 ; flt_max*256 + blt.s .lbC002936 + move.l d4,d2 ; flt_min*256 + cmp.l d5,d2 ; flt_max*256 + beq.s .filter_load_max_no_flip + neg.l d3 ; flt_speed_b*128 + move.l d5,a6 ; flt_max*256 + bra.s .filter_load_max + +.lbC002D2A + cmpi.l #$FF00,d0 + bgt.s .lbC002936 + cmp.l #$FEFF,a6 + ble.s .lbC002936 + neg.l d3 ; flt_speed_b*128 + moveq.l #0,d2 + move.l #$FF00,a6 + bra.s .filter_cont + +.lbC002936 + move.w a6,d2 + lsr.w #8,d2 + not.b d2 + bra.s .filter_cont + +.filter_load_max_no_flip + movea.l d2,a6 +.filter_load_max + moveq.l #0,d2 + move.b wi_flt_max_b(a3),d2 + not.b d2 + bra.s .filter_cont + +.filter_load_min + moveq.l #0,d2 + move.b wi_flt_min_b(a3),d2 + not.b d2 + +.filter_cont + btst #0,wi_flt_type_b(a3) + bne.s .not_notch_or_highpass +.highpass_or_notch ; entered for 2 or 4 + not.b d2 +.not_notch_or_highpass ; entered for 1 or 3 + move.w d2,d0 + add.w d0,d0 + + moveq.l #0,d7 + move.b wi_flt_resonance_b(a3),d7 + beq.s .filter_no_resonance + move.w d2,d1 + ext.l d1 + lsl.l #8,d1 + + moveq.l #$B6/2,d0 + sub.w d7,d0 + add.w d0,d0 + + cmpi.w #$36,d0 + bge.s .filter_no_clip_resonance + moveq.l #$36,d0 +.filter_no_clip_resonance + divu d0,d1 + move.w d2,d0 + add.w d1,d0 +.filter_no_resonance + lea $40(a0),a1 ; end of sample chunk + + movem.l d3-d5,-(sp) + movem.w pv_wg_flt_taps(a4),d3-d6 + + ; d0/d2 relevant for inner loop +.filter_innerloop + move.b (a0),d1 + ext.w d1 + + move.w d4,d7 + sub.w d5,d7 + muls d0,d7 + asr.l #8,d7 + sub.w d4,d7 + + add.w d1,d7 + muls d2,d7 + asr.l #8,d7 + add.w d7,d4 + move.w d4,d7 + + sub.w d5,d7 + muls d2,d7 + asr.l #8,d7 + add.w d7,d5 + move.w d5,d7 + + sub.w d6,d7 + muls d2,d7 + asr.l #8,d7 + add.w d7,d6 + move.w d6,d7 + + sub.w d3,d7 + muls d2,d7 + asr.l #8,d7 + add.w d7,d3 + move.w d3,d7 + + jmp (a2) + +.highpassfilter + sub.w d1,d7 + bra.s .filterclipresult + +.bandpassfilter + sub.w d4,d7 + sub.w d5,d7 + sub.w d6,d7 + asr.w #1,d7 + bra.s .filterclipresult + +.notchfilter + sub.w d4,d7 + neg.w d7 + +.lowpassfilter +.filterclipresult + CLIPTO8BIT d7 +.filter_outputbyte + move.b d7,(a0)+ + cmpa.l a0,a1 + bne.s .filter_innerloop + +.filterloop_end_test + movem.w d3-d6,pv_wg_flt_taps(a4) + movem.l (sp)+,d3-d5 + + cmpa.l pv_wg_curr_samend_ptr(a4),a0 + bhs.s .filter_done + move.l a6,d0 + bra .entry_to_filter_loop + +.filter_done +; ---------------------------------------- +; Optional Pre-Modulator + btst #5,wi_mod_density_b(a3) ; post bit + bne.s .nopremodulator + bsr pre_Modulator +.nopremodulator + +; ---------------------------------------- +; start with volume envelope +; a0 = output sample buffer +; d0 = scratch (e.g. sample) +; d1 = increment for attack phase +; d3 = current volume for attack and decay phases +; d4 = remaining sample length - 1 +; a3 = wave info + +.vol_do_envelope + movea.l pv_wg_curr_sample_ptr(a4),a0 ; load buffer pointer + move.w pv_wg_curr_sample_len_w(a4),d4 ; load length + IFNE PRETRACKER_PARANOIA_MODE + beq .vol_envelope_finished ; paranoia + ENDC + subq.w #1,d4 ; we use length-1, <0 is end + + moveq.l #2,d1 ; turns into $20000 through swap + moveq.l #0,d0 + move.b wi_vol_attack_b(a3),d0 + bne.s .has_attack_volume + cmpi.b #$FF,wi_vol_sustain_b(a3) + beq .vol_envelope_finished + ; no attack but not full sustain -> go to delay + ;move.l #$100<<16,d3 + bra.s .vol_skip_attack + +.vol_avoid_overflow_with_1 + moveq.l #1,d1 + bra.s .cont_vol_envelope +.has_attack_volume + moveq.l #0,d3 + cmp.w #1,d0 + beq.s .cont_vol_envelope + cmp.w #2,d0 + beq.s .vol_avoid_overflow_with_1 + swap d1 ; turn into $20000 + divu d0,d1 + swap d1 + clr.w d1 + ; swap is done below +.cont_vol_envelope + swap d1 ; move to high word (should be max $20000 then) + btst #5,wi_flags_b(a3) ; vol fast flag + beq.s .vol_no_fast + lsl.l #4,d1 ; multiply speed by 16 +.vol_no_fast + add.l d1,d3 ; increase volume + cmpi.l #$FFFFFF,d3 + ble.s .vol_do_attack ; first step overshooting? +.vol_skip_attack + btst #3,wi_flags_b(a3) ; boost flag + bne.s .vol_delay_boosted + bra.s .vol_delay_normal + +.vol_do_attack + btst #3,wi_flags_b(a3) ; boost flag + bne.s .vol_attack_boosted + +; ---------------------------------------- +; attack phase with volume boosted +.vol_attack_normal +.vol_attack_normal_loop + move.b (a0),d0 + ext.w d0 + swap d3 + muls d3,d0 + swap d3 + asr.w #8,d0 + move.b d0,(a0)+ + + subq.w #1,d4 + bmi .vol_envelope_finished + add.l d1,d3 ; increase volume + cmpi.l #$FFFFFF,d3 + ble.s .vol_attack_normal_loop + +; ---------------------------------------- +; delay phase (normal) + +.vol_delay_normal ; moved this label two inst up, didn't make sense there + moveq.l #0,d0 + move.b wi_vol_delay_b(a3),d0 + lsl.w #4,d0 + + IFNE PRETRACKER_FASTER_CODE + ; skip the delay -- we don't change the volume for this section + addq.w #1,d0 + sub.w d0,d4 + bmi .vol_envelope_finished + lea 1(a0,d0.w),a0 + ELSE + lea 2(a0,d0.w),a1 + + move.w #$FF,d3 ; FIXME I don't think that this is quite right. Shouldn't the max volume NOT change the value? +.vol_delay_normal_loop + move.b (a0),d0 + IFNE 1 + ext.w d0 + muls d3,d0 + asr.w #8,d0 + ELSE + ; this should be the same as above (*(256-1)) + spl d3 + add.b d3,d0 + ENDC + move.b d0,(a0)+ + + cmpa.l a1,a0 + dbeq d4,.vol_delay_normal_loop + bne .vol_envelope_finished + ENDC + + bra.s .vol_delay_end_reached + +; ---------------------------------------- +; attack with volume boosted + +.vol_attack_boosted +.vol_attack_boosted_loop + move.b (a0),d0 + ext.w d0 + swap d3 + muls d3,d0 + swap d3 + asr.w #6,d0 + CLIPTO8BIT d0 + move.b d0,(a0)+ + + subq.w #1,d4 + bmi .vol_envelope_finished + add.l d1,d3 + cmpi.l #$FFFFFF,d3 + ble.s .vol_attack_boosted_loop + +; ---------------------------------------- +; delay with max volume boosted + +.vol_delay_boosted + moveq.l #0,d0 + move.b wi_vol_delay_b(a3),d0 + lsl.w #4,d0 + + lea 2(a0,d0.w),a1 + + IFNE PRETRACKER_FASTER_CODE +.vol_delay_boosted_loop + move.b (a0),d0 + add.b d0,d0 + CLIPTO8BITAFTERADD d0 + add.b d0,d0 + CLIPTO8BITAFTERADD d0 + ELSE + move.w #$FF,d3 ; FIXME I don't think that this is quite right. It should be $100 to boost by full volume +.vol_delay_boosted_loop + move.b (a0),d0 + ext.w d0 + muls d3,d0 + asr.w #6,d0 + CLIPTO8BIT d0 + ENDC + move.b d0,(a0)+ + + cmpa.l a1,a0 + dbeq d4,.vol_delay_boosted_loop + bne .vol_envelope_finished + +.vol_delay_end_reached + subq.w #1,d4 + +; ---------------------------------------- +; decay phase +; d0 = scratch +; d1 = current volume decrement +; d2 = table index boundary +; d3 = 16:16 decay pos +; d4 = sample length counter +; d5 = volume +; d6 = scratch +; d7 = decay increment +; a0 = sample pointer +; a1 = (current) roll off table pointer (points to upper bound) +; a2 = lower bound + +.vol_do_decay + moveq.l #0,d3 + move.b wi_vol_decay_b(a3),d3 + beq .vol_do_sustain + move.w d3,d7 + mulu d7,d7 + lsr.w #2,d7 + add.w d3,d7 ; d7 = (d3^2)/4+d3 (<= 16511) + + btst #5,wi_flags_b(a3) ; vol fast flag + beq.s .vol_decay_not_fast + moveq.l #0,d3 ; will cause a5=$400,a2=$200,d2=0, decay value has no effect on the ramp used +.vol_decay_not_fast + lsl.w #8,d3 + lsl.l #4,d3 + move.l d3,d2 + swap d2 + lea pre_roll_off_table(pc),a1 + add.w d2,d2 + adda.w d2,a1 + move.w (a1)+,a2 ; first index in table + lsr.w #1,d2 ; update next boundary + + moveq.l #0,d1 ; current volume decrement + moveq.l #0,d5 + not.w d5 ; set maximum volume +.vol_decay_normal_loop + add.l d7,d3 ; increment position in decay + swap d3 + + cmp.w #$8e,d3 ; pos in table where it makes no sense to do lerp anymore + bhi.s .vol_keep_voldec + cmp.w d2,d3 + bls.s .vol_do_lerp + +.vol_lerp_next_section + move.w (a1),a2 + IFNE PRETRACKER_BUGFIX_CODE + lea pre_roll_off_table+2(pc),a1 ; Take the right boundary value + ELSE + lea pre_roll_off_table(pc),a1 ; This will set a wrong boundary and thus plateau the slope decay speed + ENDC + add.w d3,a1 + add.w d3,a1 + + move.w d3,d2 ; update next boundary + +.vol_do_lerp ; ((lowerbound-upperbound)*(d3<<8))>>8 + upperbound + move.w a2,d1 + move.w (a1),d0 + sub.w d1,d0 ; delta between lower and upper bound (negative value) + beq.s .vol_skip_lerp + + swap d3 + move.w d3,d1 + lsr.w #8,d1 + muls d0,d1 + asr.l #8,d1 + add.w a2,d1 + swap d3 + +.vol_keep_voldec +.vol_skip_lerp + swap d3 + sub.w d1,d5 + bls.s .vol_do_sustain + + move.w d5,d6 + lsr.w #8,d6 + + cmp.b wi_vol_sustain_b(a3),d6 + bls.s .vol_do_sustain + + move.b (a0),d0 + ext.w d0 + muls d6,d0 + btst #3,wi_flags_b(a3) ; boost flag + CLIPORTRUNC8BIT d0 + move.b d0,(a0)+ + + dbra d4,.vol_decay_normal_loop + bra.s .vol_envelope_finished + +; ---------------------------------------- +; sustain phase +.vol_do_sustain + moveq.l #0,d3 + move.b wi_vol_sustain_b(a3),d3 + beq.s .vol_sustain_silence + + btst #3,wi_flags_b(a3) ; boost flag + beq.s .vol_sustain_normal +.vol_sustain_boosted +.vol_sustain_boosted_loop + move.b (a0),d0 + ext.w d0 + muls d3,d0 + asr.w #6,d0 + + CLIPTO8BIT d0 + move.b d0,(a0)+ + dbra d4,.vol_sustain_boosted_loop + bra.s .vol_envelope_finished + +.vol_sustain_silence + moveq.l #0,d0 +.vol_sustain_silence_loop + move.b d0,(a0)+ + dbra d4,.vol_sustain_silence_loop + bra.s .vol_envelope_finished + +.vol_sustain_normal + IFNE PRETRACKER_FASTER_CODE + cmp.b #$ff,d3 + beq.s .vol_envelope_finished + ENDC + +.vol_sustain_normal_loop + move.b (a0),d0 + ext.w d0 + muls d3,d0 + asr.w #8,d0 + move.b d0,(a0)+ + dbra d4,.vol_sustain_normal_loop + +.vol_envelope_finished + +; ---------------------------------------- +; Optional Post-Modulator + + btst #5,wi_mod_density_b(a3) ; post bit + beq.s .nopostmodulator + bsr pre_Modulator +.nopostmodulator + +; ---------------------------------------- +; wave mixing (removed some code here that was doing nothing as result +; because below higher octaves code would overwrite it anyway). + movea.l pv_my_song(a4),a6 + + moveq.l #0,d0 + move.b wi_mix_wave_b(a3),d0 + beq.s .mix_no_wave_mixing ; no mixing selected + subq.b #1,d0 + IFNE PRETRACKER_PARANOIA_MODE ; same wave for mixing cannot be selected in Pretracker + cmp.b pv_wg_curr_wave_num_b(a4),d0 + beq .mix_no_wave_mixing ; same wave number! + ENDC + + lsl.w #2,d0 + move.l sv_wavelength_table(a6,d0.w),d3 + move.l pv_wave_sample_table(a4,d0.w),a1 + + move.w pv_wg_curr_sample_len_w(a4),d4 ; length of the sample to mix to + cmp.w d3,d4 + ble.s .mix_picked_shorter + move.w d3,d4 +.mix_picked_shorter + + move.l pv_wg_curr_sample_ptr(a4),a0 + + subq.w #1,d4 +.mix_mixloop + move.b (a0),d0 + add.b (a1)+,d0 + CLIPTO8BITAFTERADD d0 + move.b d0,(a0)+ + dbra d4,.mix_mixloop +.mix_no_wave_mixing + +; ---------------------------------------- +; create higher octaves (this has been massively shortened) + + btst #2,wi_flags_b(a3) + beq.s .oct_has_no_extra_octaves + + moveq.l #0,d4 + move.b wi_sam_len_b(a3),d4 ; length of the sample + IFNE PRETRACKER_PARANOIA_MODE + beq.s .oct_has_no_extra_octaves + ENDC + addq.w #1,d4 + lsl.w #7,d4 + + movea.l pv_wg_curr_sample_ptr(a4),a1 + lea (a1,d4.l),a0 ; needs to be .l due to 32678 max length + + mulu #7,d4 + lsr.l #3,d4 ; * 0.875 + subq.w #1,d4 +.oct_downsample_loop + move.b (a1),(a0)+ + addq.l #2,a1 + dbra d4,.oct_downsample_loop + +.oct_has_no_extra_octaves +; ---------------------------------------- + IFNE PRETRACKER_PROGRESS_SUPPORT + move.l pv_precalc_progress_ptr(a4),d0 + beq.s .no_progress_out + move.l d0,a0 + move.l pv_precalc_sample_size(a4),d0 + add.l d0,(a0) +.no_progress_out + ENDC + move.b sv_num_waves_b(a6),d0 + addq.b #1,pv_wg_wave_ord_num_w+1(a4) + cmp.b pv_wg_wave_ord_num_w+1(a4),d0 + bgt .wavegenloop + +; ---------------------------------------- + IFNE PRETRACKER_VOLUME_TABLE + lea pv_volume_table(a4),a0 + moveq.l #(MAX_VOLUME+1)-1,d7 + moveq.l #0,d0 +.vol_outerloop + moveq.l #MAX_VOLUME*2-1,d6 + moveq.l #0,d1 +.vol_innerloop + move.w d1,d2 + lsr.w #6,d2 + move.b d2,(a0)+ + add.w d0,d1 + dbra d6,.vol_innerloop + addq.w #1,d0 + dbra d7,.vol_outerloop + ENDC + +; ---------------------------------------- +.earlyexit + IFNE PRETRACKER_DONT_TRASH_REGS + movem.l (sp)+,d2-d7/a2-a6 + ENDC + rts + +;-------------------------------------------------------------------- +; a3: waveinfo +; +; d6: wetness (word) +; uses all data registers and a0-a2 (a3 unchanged) +pre_Modulator: + tst.b wi_mod_wetness_b(a3) + beq.s .earlyexit + moveq.l #7,d0 + and.b wi_mod_density_b(a3),d0 + bne.s .has_density +.earlyexit + rts +.has_density + move.l pv_wg_curr_sample_ptr(a4),a0 + move.w pv_wg_curr_sample_len_w(a4),d4 + IFNE PRETRACKER_PARANOIA_MODE + bne.s .not_zero + rts +.not_zero + ENDC + moveq.l #0,d6 + move.b wi_mod_wetness_b(a3),d6 + + moveq.l #0,d7 + + lea pre_modulator_ramp_8(pc),a1 + lea pre_ramp_up_down_32(pc),a2 +.loop moveq.l #0,d5 + move.b wi_mod_length_b(a3),d5 + mulu (a1)+,d5 ; result is a long value + + moveq.l #0,d1 + move.b wi_mod_predelay_b(a3),d1 + + btst #5,wi_mod_density_b(a3) ; post-modulator? + bne.s .factor1_256 + ; factor 1/4 and 64 + lsr.l #2,d5 + lsl.l #6,d1 + bra.s .cont + +.factor1_256 + lsl.w #8,d1 +.cont add.l d1,d5 ; sum up length and predelay + + moveq.l #0,d2 + moveq.l #0,d3 + +.innerloop + add.w d7,d3 + addq.w #8,d3 + moveq.l #0,d1 + move.w d3,d1 + lsr.w #8,d1 + lsr.w #3,d1 + add.w d1,d1 + move.w (a2,d1.w),d1 ; 4 bit value + add.l d5,d1 + lsr.l #6,d1 + + move.w d2,d0 + sub.w d1,d0 + bmi.s .isneg + + move.b (a0,d0.w),d1 + ext.w d1 + btst #0,d7 + beq.s .keep_dc + neg.w d1 +.keep_dc + + muls d6,d1 + asr.w #8,d1 + add.b (a0,d2.w),d1 + + CLIPTO8BITAFTERADD d1 + move.b d1,(a0,d2.w) +.isneg + addq.w #1,d2 + cmp.w d4,d2 + bcs.s .innerloop + +.restartloop + addq.w #1,d7 + moveq.l #7,d0 + and.b wi_mod_density_b(a3),d0 + cmp.w d0,d7 + bcs.s .loop + rts + +;-------------------------------------------------------------------- + +pre_MemClr + lsr.w #1,d0 + subq.w #1,d0 + bmi.s .skipmemclr + moveq.l #0,d1 +.fillmemloop + move.w d1,(a0)+ + dbra d0,.fillmemloop +.skipmemclr + rts + +;******************************************************************** +;-------------------------------------------------------------------- +; PlayerTick - Play one frame of music (called every VBL) +; +; In: +; - a0: MyPlayer +; - a1: copperlist (if enabled) +;******************************************************************** +pre_PlayerTick: + IFNE PRETRACKER_DONT_TRASH_REGS + movem.l d2-d7/a2-a6,-(sp) + ENDC + move.l a0,a4 + IFNE PRETRACKER_COPPER_OUTPUT + move.l a1,pv_copperlist_ptr(a4) + ENDC + movea.l pv_my_song(a4),a6 + tst.b pv_pat_stopped_b(a4) + beq .inst_pattern_processing ; don't process if music has been stopped + +; ---------------------------------------- +; processes the current pattern position +; registers used: +; d0: pitch shift (lower part) +; d1: scratch +; d2: effect cmd +; d3: pitch_ctrl +; d4: inst number +; d5: effect cmd +; d6: unused (flag later) +; d7: pitch +; a0: pattern data pointer +; a1: short-term scratch +; a2: unused +; a3: unused +; a4: pv +; a5: channel struct +; a6: mysong struct +.process_pattern + lea pv_channeldata(a4),a5 ; start with first channel +.pre_pat_chan_loop + IFNE PRETRACKER_PARANOIA_MODE + ; I think this is something leftover from the tracker itself. + ; Nothing sets pcd_pat_adsr_rel_delay_b from inside the player. + ; It is used as a counter to release a note (ADSR) after a given time. + ; It's not the same as the instrument ADSR release (see pcd_note_off_delay_b) + move.b pcd_pat_adsr_rel_delay_b(a5),d1 + ble.s .handle_2nd_instrument + subq.b #1,d1 + move.b d1,pcd_pat_adsr_rel_delay_b(a5) + bne.s .handle_2nd_instrument + + move.w pcd_adsr_volume_w(a5),d3 + lsr.w #6,d3 + move.w d3,pcd_adsr_vol64_w(a5) + moveq.l #16,d4 + move.w d4,pcd_adsr_pos_w(a5) + sub.w d3,d4 + lsr.w #1,d4 + add.b pcd_adsr_release_b(a5),d4 + move.b d4,pcd_adsr_phase_speed_b(a5) + move.w #3,pcd_adsr_phase_w(a5) + ENDC + +; ---------------------------------------- +.handle_2nd_instrument + moveq.l #0,d1 + move.b pcd_pat_2nd_inst_num_b(a5),d1 + beq.s .handle_current_instrument + + move.b pcd_pat_2nd_inst_delay_b(a5),d3 + beq.s .trigger_2nd_instrument + subq.b #1,d3 + move.b d3,pcd_pat_2nd_inst_delay_b(a5) + bra.s .handle_current_instrument + +.trigger_2nd_instrument + move.w d1,pcd_inst_num_w(a5) + move.b d1,pcd_new_inst_num_b(a5) + lsl.w #4,d1 + lea sv_inst_infos_table-uii_SIZEOF(a6),a1 + add.w d1,a1 + move.l a1,pcd_inst_info_ptr(a5) ; loads 2nd instrument + move.b uii_pattern_steps(a1),pcd_inst_pattern_steps_b(a5) + + moveq.l #0,d1 + move.l a5,a1 + move.l d1,(a1)+ ; pcd_pat_portamento_dest_w and pcd_pat_pitch_slide_w + move.l d1,(a1)+ ; pcd_pat_vol_ramp_speed_b, pcd_pat_2nd_inst_num_b, pcd_pat_2nd_inst_delay_b, pcd_wave_offset_b + move.l d1,(a1)+ ; pcd_inst_pitch_slide_w and pcd_inst_sel_arp_note_w + move.w d1,(a1)+ ; pcd_inst_note_pitch_w + addq.w #2,a1 + + move.l d1,(a1)+ ; pcd_inst_line_ticks_b, pcd_inst_pitch_pinned_b, pcd_inst_vol_slide_b, pcd_inst_step_pos_b + + subq.b #1,d1 + move.w d1,(a1)+ ; pcd_inst_wave_num_w + + move.l #$ff010010,(a1)+ ; pcd_track_delay_offset_b, pcd_inst_speed_stop_b, pcd_inst_pitch_w + move.l #(MAX_VOLUME<<16)|(MAX_VOLUME<<8)|MAX_VOLUME,(a1)+ ; pcd_inst_vol_w / pcd_loaded_inst_vol_b / pcd_pat_vol_b + + bra.s .continue_with_inst + +; ---------------------------------------- +.handle_current_instrument + +; ---------------------------------------- +; handle portamento + move.w pcd_pat_portamento_dest_w(a5),d3 + beq.s .no_portamento_active + move.w pcd_inst_curr_port_pitch_w(a5),d2 + moveq.l #0,d1 + move.b pcd_pat_portamento_speed_b(a5),d1 + cmp.w d3,d2 + bge.s .do_portamento_down + add.w d1,d2 + cmp.w d3,d2 + bgt.s .portamento_note_reached + bra.s .update_portamento_value + +.do_portamento_down + sub.w d1,d2 + cmp.w d3,d2 + bge.s .update_portamento_value + +.portamento_note_reached + clr.w pcd_pat_portamento_dest_w(a5) + move.w d3,d2 +.update_portamento_value + move.w d2,pcd_inst_curr_port_pitch_w(a5) +.no_portamento_active + +; ---------------------------------------- +; handle volume ramping + move.b pcd_pat_vol_ramp_speed_b(a5),d1 + beq.s .no_vol_ramping_active + add.b pcd_pat_vol_b(a5),d1 + bpl.s .noclip_pat_vol_min + moveq.l #0,d1 +.noclip_pat_vol_min + cmpi.b #MAX_VOLUME,d1 + ble.s .noclip_pat_vol_max + moveq.l #MAX_VOLUME,d1 +.noclip_pat_vol_max + move.b d1,pcd_pat_vol_b(a5) +.no_vol_ramping_active + +; ---------------------------------------- +; enters with channel number in d0 + +.continue_with_inst + ; handle delayed note and note off first + moveq.l #0,d4 + move.b pcd_note_delay_b(a5),d4 + blt .pat_play_cont + beq.s .no_note_delay + subq.b #1,d4 + beq.s .note_delay_end_reached + + move.b d4,pcd_note_delay_b(a5) ; note still delayed + IFNE PRETRACKER_BUGFIX_CODE + bra .pat_play_cont ; I believe that with activated track delay, we must jump here + ELSE + bra .pat_channels_loop_test + ENDC + +.note_delay_end_reached + st pcd_note_delay_b(a5) ; release note delay +.no_note_delay + moveq.l #0,d5 + move.b pcd_channel_num_b(a5),d5 + move.w sv_curr_pat_pos_w(a6),d2 + add.w d2,d2 + add.w d2,d2 ; *4 + add.w d5,d2 + add.w d2,d2 ; 8*pos+2*chan + movea.l sv_pos_data_adr(a6),a1 + adda.w d2,a1 + ;move.l a1,d2 + ;cmpa.w #0,a1 + ;beq .pat_play_other ; this is probably never happening! + moveq.l #0,d2 + move.b pv_pat_curr_row_b(a4),d2 + cmp.b sv_num_steps_b(a6),d2 + bcc .pat_play_cont + + move.b ppd_pat_num(a1),d5 + beq .pat_play_cont + add.w d5,d5 + add.w d5,d5 + add.w #sv_pattern_table,d5 + move.l -4(a6,d5.w),a0 + IFNE PRETRACKER_PARANOIA_MODE + move.l a0,d5 ; move to data register due to cc's + beq .pat_play_cont + ENDC + + move.b ppd_pat_shift(a1),d0 ; pattern pitch shift (signed) + ext.w d0 + + add.w d2,a0 + add.w d2,d2 + add.w d2,a0 ; pattern data + + moveq.l #15,d2 + move.b pdb_inst_effect(a0),d4 ; instrument and command byte + and.w d4,d2 + lsr.w #4,d4 ; instrument nr bits 0-4 + + moveq.l #0,d5 + move.b pdb_effect_data(a0),d5 + + cmpi.b #$e,d2 + bne.s .pat_exy_cmd_cont + ; handle $exy commands + tst.b pcd_note_delay_b(a5) + bne.s .pat_exy_cmd_cont ; ignore if already running note delay + move.l d5,d3 + moveq.l #15,d1 + and.w d3,d1 + lsr.w #4,d3 + sub.w #$d,d3 + bne.s .pat_is_not_ed_cmd + ; note delay in x sub steps + IFNE PRETRACKER_PARANOIA_MODE ; who does this kind of stuff? + tst.b pv_pat_speed_b(a4) + beq.s .pat_exy_cmd_cont + ENDC + move.b d1,pcd_note_delay_b(a5) + IFNE PRETRACKER_BUGFIX_CODE + bra .pat_play_cont ; I believe that with activated track delay, we must jump here + ELSE + bra .pat_channels_loop_test + ENDC + +.pat_is_not_ed_cmd + addq.b #$d-$a,d3 + bne.s .pat_exy_cmd_cont + ; note off in x sub steps + move.b d1,pcd_note_off_delay_b(a5) + +.pat_exy_cmd_cont + st pcd_note_delay_b(a5) + +; ---------------------------------------- +; read out pattern editor data + + move.b pdb_pitch_ctrl(a0),d3 ; pitch and control byte + bpl.s .noselinst16plus + add.w #16,d4 ; add high bit of instrument number +.noselinst16plus + moveq.l #$3f,d7 + and.w d3,d7 ; pitch + tst.w d4 + beq.s .no_new_note ; if no instrument + tst.w d7 + bne.s .no_new_note ; if it has pitch + + ; only change of instrument, not pitch + move.b pcd_loaded_inst_vol_b(a5),pcd_pat_vol_b(a5) + + cmp.w pcd_inst_num_w(a5),d4 + bne.s .no_new_note + clr.w pcd_adsr_phase_w(a5) ; attack! + clr.w pcd_adsr_volume_w(a5) + ;move.b #1,pcd_adsr_trigger_b(a5) ; never read + +.no_new_note + +; d2 = effect cmd, d3 = pitch_ctrl, d4 = inst number, d5 = effect data, d7 = pitch + + moveq.l #0,d6 ; clear arp flag + + andi.b #$40,d3 ; ARP bit + bne.s .has_arp_note +.no_arp_note + tst.b d2 + bne.s .arp_processing_done + ; 0xx: play second instrument + tst.b d5 + beq.s .no_effect + moveq.l #15,d1 ; FIXME seems like it only supports the lower 15 instruments + and.b d5,d1 + + tst.b d7 + bne.s .play_2nd_inst_without_trigger + +.play_2nd_inst_with_no_pitch + addq.w #1,d0 ; pattern pitch shift + lsl.w #4,d0 + + tst.b d1 + beq.s .clear_note_arp + + moveq.l #0,d2 + move.w d4,d3 + move.w d1,d4 + bra.s .trigger_new_instrument + +.play_2nd_inst_without_trigger + move.w d4,d3 ; 1st instrument num + move.w d1,d4 ; 2nd instrument num + bra.s .arp_processing_done + +.clear_note_arp + clr.l pcd_arp_notes_l(a5) + move.b d7,d2 + move.b d4,d3 + bra .clear_portamento + +.has_arp_note + move.b d2,d3 + or.b d5,d3 + beq.s .all_arp_notes_zero ; if we go there, d3 MUST be 0 already + + move.b d2,pcd_arp_note_1_b(a5) + + move.b d5,d2 + lsr.b #4,d2 + move.b d2,pcd_arp_note_2_b(a5) + + moveq.l #15,d2 + and.b d5,d2 + move.b d2,pcd_arp_note_3_b(a5) + +.all_arp_notes_zero + moveq.l #1,d6 +.no_effect + moveq.l #0,d2 ; make sure we don't get a random command here + moveq.l #0,d3 + +; ---------------------------------------- +; d2 = effect cmd, d3 = alt inst number (or 0), d4 = inst number, d5 = effect cmd, d6 = ARP flag, d7 = pitch + +.arp_processing_done + cmpi.b #NOTE_OFF_PITCH,d7 + bne.s .has_no_note_off + +.release_note + ; release note + ; FIXME we have the identical code (different regs) three times (one is inactive) + move.w pcd_adsr_volume_w(a5),d4 + asr.w #6,d4 + move.w d4,pcd_adsr_vol64_w(a5) + moveq.l #16,d7 + move.w d7,pcd_adsr_pos_w(a5) + sub.w d4,d7 + lsr.w #1,d7 + add.b pcd_adsr_release_b(a5),d7 + move.b d7,pcd_adsr_phase_speed_b(a5) + move.w #3,pcd_adsr_phase_w(a5) + bra .start_patt_effect_handling + +.has_inst_number + add.w d7,d0 ; pattern pitch shift? + lsl.w #4,d0 + + cmpi.b #3,d2 ; is command portamento? + beq.s .pat_set_portamento + +.trigger_new_instrument + move.w d4,d1 + + move.w d1,pcd_inst_num_w(a5) + move.b d1,pcd_new_inst_num_b(a5) + lsl.w #4,d1 + lea sv_inst_infos_table-uii_SIZEOF(a6),a1 + add.w d1,a1 + move.l a1,pcd_inst_info_ptr(a5) + move.b uii_pattern_steps(a1),pcd_inst_pattern_steps_b(a5) + + moveq.l #0,d1 + move.l a5,a1 + move.l d1,(a1)+ ; pcd_pat_portamento_dest_w and pcd_pat_pitch_slide_w + move.l d1,(a1)+ ; pcd_pat_vol_ramp_speed_b, pcd_pat_2nd_inst_num_b, pcd_pat_2nd_inst_delay_b, pcd_wave_offset_b + move.l d1,(a1)+ ; pcd_inst_pitch_slide_w and pcd_inst_sel_arp_note_w + move.l d1,(a1)+ ; pcd_inst_note_pitch_w and pcd_inst_curr_port_pitch_w + + move.l d1,(a1)+ ; pcd_inst_line_ticks_b, pcd_inst_pitch_pinned_b, pcd_inst_vol_slide_b, pcd_inst_step_pos_b + + subq.b #1,d1 + move.w d1,(a1)+ ; pcd_inst_wave_num_w + + move.l #$ff010010,(a1)+ ; pcd_track_delay_offset_b, pcd_inst_speed_stop_b, pcd_inst_pitch_w + move.l #(MAX_VOLUME<<16)|(MAX_VOLUME<<8)|MAX_VOLUME,(a1)+ ; pcd_inst_vol_w / pcd_loaded_inst_vol_b / pcd_pat_vol_b + + bra.s .cont_after_inst_trigger + +.has_no_note_off + tst.b d7 + beq.s .start_patt_effect_handling + tst.b d4 + bne.s .has_inst_number + + add.w d7,d0 ; pattern pitch shift + lsl.w #4,d0 + +.cont_after_inst_trigger + tst.b d6 ; has ARP? + bne.s .lbC001852 + bra.s .lbC00193C + +.pat_set_portamento + tst.b d6 + bne.s .pat_new_portamento +.lbC00193C + clr.l pcd_arp_notes_l(a5) + moveq.l #0,d6 + +.lbC001852 + cmpi.b #3,d2 ; is command portamento? + beq.s .pat_new_portamento + +.clear_portamento + move.w #$10,pcd_inst_pitch_w(a5) + move.w d0,pcd_inst_curr_port_pitch_w(a5) + clr.w pcd_pat_portamento_dest_w(a5) + bra.s .start_patt_effect_handling + +.pat_new_portamento + add.w #$10,d0 ; pattern pitch shift + move.w d0,pcd_pat_portamento_dest_w(a5) + + move.w pcd_inst_pitch_w(a5),d1 + add.w d1,pcd_inst_curr_port_pitch_w(a5) + clr.w pcd_inst_pitch_w(a5) + tst.b d5 + beq.s .pat_keep_old_portamento + move.b d5,pcd_pat_portamento_speed_b(a5) +.pat_keep_old_portamento + +; ---------------------------------------- +.start_patt_effect_handling + ; FIXME can we move this code to avoid blocking the two registers d3/d5 + tst.b d3 + beq.s .has_no_second_inst + move.b d3,pcd_pat_2nd_inst_num_b(a5) + move.b d5,d3 + lsr.b #4,d3 + move.b d3,pcd_pat_2nd_inst_delay_b(a5) + +.has_no_second_inst + clr.b pcd_pat_vol_ramp_speed_b(a5) + clr.w pcd_pat_pitch_slide_w(a5) + tst.b d6 + bne .pat_play_cont + add.w d2,d2 + move.w .pattern_command_jmptable(pc,d2.w),d2 + jmp .pattern_command_jmptable(pc,d2.w) + +.pattern_command_jmptable + dc.w .pat_play_nop-.pattern_command_jmptable + dc.w .pat_slide_up-.pattern_command_jmptable + dc.w .pat_slide_down-.pattern_command_jmptable + dc.w .pat_play_nop-.pattern_command_jmptable + dc.w .pat_set_vibrato-.pattern_command_jmptable + dc.w .pat_set_track_delay-.pattern_command_jmptable + dc.w .pat_play_nop-.pattern_command_jmptable + dc.w .pat_play_nop-.pattern_command_jmptable + dc.w .pat_play_nop-.pattern_command_jmptable + dc.w .pat_set_wave_offset-.pattern_command_jmptable + dc.w .pat_volume_ramp-.pattern_command_jmptable + dc.w .pat_pos_jump-.pattern_command_jmptable + dc.w .pat_set_volume-.pattern_command_jmptable + dc.w .pat_pat_break-.pattern_command_jmptable + dc.w .pat_play_nop-.pattern_command_jmptable + dc.w .pat_set_speed-.pattern_command_jmptable + +; d5 = command parameter data +; ---------------------------------------- +.pat_set_vibrato + clr.w pcd_vibrato_pos_w(a5) + move.w #1,pcd_vibrato_delay_w(a5) + moveq.l #15,d2 + and.w d5,d2 + + lea pre_vib_depth_table(pc),a1 + move.b (a1,d2.w),pcd_vibrato_depth_w+1(a5) + lsr.b #4,d5 + move.b pre_vib_speed_table-pre_vib_depth_table(a1,d5.w),d2 + move.w d2,pcd_vibrato_speed_w(a5) + bra .pat_play_cont + +; ---------------------------------------- +.pat_set_track_delay + cmp.b #NUM_CHANNELS-1,pcd_channel_num_b(a5) + beq.s .pat_play_cont ; we are at channel 3 -- track delay not available here + + lea pcd_SIZEOF+pcd_track_delay_buffer+ocd_volume(a5),a1 + moveq.l #MAX_TRACK_DELAY-1,d2 +.clr_track_delay_buffer_loop + clr.b (a1) ; ocd_volume + lea ocd_SIZEOF(a1),a1 + dbra d2,.clr_track_delay_buffer_loop + + tst.b d5 + bne.s .pat_track_delay_set + st pcd_track_delay_steps_b(a5) + bra.s .handle_track_delay + +.pat_track_delay_set + moveq.l #15,d2 + and.b d5,d2 + add.b d2,d2 + move.b d2,pcd_track_delay_steps_b(a5) +; subq.b #1,d2 +; move.b d2,pcd_SIZEOF+pcd_track_init_delay_b(a5) + lsr.b #4,d5 + move.b d5,pcd_track_delay_vol16_b(a5) + bra.s .pat_play_cont + +; ---------------------------------------- +.pat_slide_down + neg.w d5 +.pat_slide_up + move.w d5,pcd_pat_pitch_slide_w(a5) + bra.s .pat_play_cont + +; ---------------------------------------- +.pat_set_wave_offset + move.b d5,pcd_wave_offset_b(a5) + bra.s .pat_play_cont + +; ---------------------------------------- +.pat_volume_ramp + tst.b d5 + beq.s .pat_play_cont + moveq.l #15,d3 + and.b d5,d3 + beq.s .pat_vol_ramp_up + ; NOTE: Changed behaviour: using d3 instead of d5 + ; if both lower and upper were specified, this + ; probably led to a drastic decrease of volume. + neg.b d3 + move.b d3,pcd_pat_vol_ramp_speed_b(a5) + bra.s .pat_play_cont +.pat_vol_ramp_up + lsr.b #4,d5 + move.b d5,pcd_pat_vol_ramp_speed_b(a5) + bra.s .pat_play_cont + +; ---------------------------------------- +.pat_pos_jump + move.b d5,pv_next_pat_pos_b(a4) + bra.s .pat_play_cont + +; ---------------------------------------- +.pat_set_volume + cmpi.b #MAX_VOLUME,d5 + bls.s .pat_set_volume_nomax + moveq.l #MAX_VOLUME,d5 +.pat_set_volume_nomax + move.b d5,pcd_pat_vol_b(a5) + bra.s .pat_play_cont + +; ---------------------------------------- +.pat_pat_break + move.b d5,pv_next_pat_row_b(a4) + bra.s .pat_play_cont + +; ---------------------------------------- +.pat_set_speed + move.b d5,pv_pat_speed_b(a4) + sne d2 + neg.b d2 + move.b d2,pv_pat_stopped_b(a4) + IFNE PRETRACKER_SONG_END_DETECTION + bne.s .pat_no_songend + st pv_songend_detected_b(a4) +.pat_no_songend + ENDC + + bsr pre_update_pat_line_counter + +; ---------------------------------------- + +.pat_play_nop +.pat_play_cont + move.b pcd_track_delay_steps_b(a5),d2 ; FIXME this is a mess + beq.s .pat_channels_loop_test + +.handle_track_delay + lea pcd_SIZEOF(a5),a5 + cmp.b #NUM_CHANNELS-2,pcd_channel_num_b-pcd_SIZEOF(a5) ; FIXME find out why we need this + bge.s .pat_channels_loop_end + +.pat_channels_loop_test + lea pcd_SIZEOF(a5),a5 + cmp.b #NUM_CHANNELS-1,pcd_channel_num_b-pcd_SIZEOF(a5) + bne .pre_pat_chan_loop +.pat_channels_loop_end + +; end of pattern loop + +; ---------------------------------------- +; pattern advancing FIXME try to figure out all the cases +.pattern_advancing + subq.b #1,pv_pat_line_ticks_b(a4) + bne .inst_pattern_processing + + moveq.l #0,d1 + REPT NUM_CHANNELS + move.b d1,pv_channeldata+pcd_note_delay_b+REPTN*pcd_SIZEOF(a4) + ENDR + + move.b sv_num_steps_b(a6),d1 + subq.b #1,d1 + move.b pv_next_pat_row_b(a4),d0 + blt.s .no_pattern_break + cmp.b d0,d1 + bgt.s .has_legal_break_pos + move.b d1,d0 ; limit to last step +.has_legal_break_pos + move.b d0,pv_pat_curr_row_b(a4) + + move.w sv_curr_pat_pos_w(a6),d3 ; go to next pattern pos + addq.w #1,d3 + + cmp.w sv_pat_pos_len_w(a6),d3 + blt.s .no_restart_song + move.w sv_pat_restart_pos_w(a6),d3 + IFNE PRETRACKER_SONG_END_DETECTION + st pv_songend_detected_b(a4) + ENDC +.no_restart_song + move.w d3,sv_curr_pat_pos_w(a6) + + st pv_next_pat_row_b(a4) ; processed break, set to $ff + + move.b pv_next_pat_pos_b(a4),d3 + bge.s .has_new_position ; has a new pattern position together with a break + move.b d0,d2 ; backup pv_pat_curr_row_b + cmp.b d0,d1 + ble.s .end_of_pattern_reached + bra.s .done_pat_advance + +.no_pattern_break + move.b pv_next_pat_pos_b(a4),d3 + bge.s .has_new_position + move.b pv_pat_curr_row_b(a4),d0 + move.b d0,d2 + cmp.b d1,d2 + blt.s .advancetonextpos + +.end_of_pattern_reached + clr.b pv_pat_curr_row_b(a4) + IFNE PRETRACKER_PARANOIA_MODE + move.b pv_loop_pattern_b(a4),d0 ; keep same pattern rolling? + bne .done_pat_advance + ENDC + bra.s .advance_song_pos + +.advancetonextpos + addq.b #1,d2 + move.b sv_num_steps_b(a6),d1 + addq.b #1,d0 + cmp.b d2,d1 + bgt.s .dont_go_to_top_row + moveq.l #0,d0 +.dont_go_to_top_row + move.b d0,pv_pat_curr_row_b(a4) + bra.s .done_pat_advance + +.has_new_position + clr.b pv_pat_curr_row_b(a4) + IFNE PRETRACKER_PARANOIA_MODE + move.b pv_loop_pattern_b(a4),d0 + bne .no_restart_song_after_jump + ENDC + + cmp.w sv_pat_pos_len_w(a6),d3 + blt.s .set_song_pos2 + move.w sv_pat_restart_pos_w(a6),d3 + IFNE PRETRACKER_SONG_END_DETECTION + st pv_songend_detected_b(a4) + ENDC +.set_song_pos2 + move.w d3,sv_curr_pat_pos_w(a6) + ; enters with d0 = 0 +.no_restart_song_after_jump + st pv_next_pat_pos_b(a4) ; processed jump, set to $ff + + subq.b #1,d2 + bhi.s .done_pat_advance + clr.b pv_pat_curr_row_b(a4) + tst.b d0 + bne.s .done_pat_advance + +.advance_song_pos + move.w sv_curr_pat_pos_w(a6),d0 + addq.w #1,d0 + cmp.w sv_pat_pos_len_w(a6),d0 + blt.s .set_song_pos + move.w sv_pat_restart_pos_w(a6),d0 + IFNE PRETRACKER_SONG_END_DETECTION + st pv_songend_detected_b(a4) + ENDC +.set_song_pos + move.w d0,sv_curr_pat_pos_w(a6) +.done_pat_advance + bsr pre_update_pat_line_counter + +; ---------------------------------------- +; processes the instrument pattern for each running instrument +; registers used: +; d0: pitch +; d1: volume +; d2: inst num +; d3: scratch +; a0: pattern data pointer +; a1: scratch +; a2: instrument info +; a3: wave info +; a4: pv +; a5: channel struct +; a6: mysong struct +.inst_pattern_processing + lea pv_channeldata(a4),a5 + +.inst_chan_loop + move.l pcd_waveinfo_ptr(a5),a3 + + move.l pcd_inst_info_ptr(a5),a2 + move.l a2,d3 + beq .inst_no_inst_active + + ; calculate pitch -- funny that there is no min check (seems to happen later though) + move.w pcd_inst_pitch_slide_w(a5),d0 + add.w pcd_pat_pitch_slide_w(a5),d0 + beq.s .inst_no_pitch_slides_active + add.w pcd_inst_pitch_w(a5),d0 + cmp.w #(3*NOTES_IN_OCTAVE)<<4,d0 + ble.s .inst_noclip_pitch_max + move.w #(3*NOTES_IN_OCTAVE)<<4,d0 +.inst_noclip_pitch_max + move.w d0,pcd_inst_pitch_w(a5) +.inst_no_pitch_slides_active + + move.b pcd_inst_vol_slide_b(a5),d1 + beq.s .inst_no_vol_slide_active + add.b pcd_inst_vol_w+1(a5),d1 + bpl.s .inst_noclip_vol_zero + moveq.l #0,d1 +.inst_noclip_vol_zero + cmp.b #MAX_VOLUME,d1 + ble.s .inst_noclip_vol_max + moveq.l #MAX_VOLUME,d1 +.inst_noclip_vol_max + move.b d1,pcd_inst_vol_w+1(a5) + +.inst_no_vol_slide_active + move.b pcd_inst_line_ticks_b(a5),d2 + bne .inst_still_ticking + + moveq.l #0,d0 + move.w d0,pcd_inst_pitch_slide_w(a5) + move.b d0,pcd_inst_vol_slide_b(a5) + moveq.l #-1,d4 + +; IFNE PRETRACKER_PARANOIA_MODE ; new step is never written +; move.w pcd_inst_new_step_w(a5),d1 +; blt.s .inst_no_new_step_pos +; cmpi.w #$20,d1 +; ble.s .inst_good_new_step_pos +; moveq.l #$20,d1 +;.inst_good_new_step_pos +; move.b d1,pcd_inst_step_pos_b(a5) +; move.w d4,pcd_inst_new_step_w(a5) +;.inst_no_new_step_pos +; ENDC + move.b pcd_inst_step_pos_b(a5),d0 + cmp.b pcd_inst_pattern_steps_b(a5),d0 + bhs .inst_pat_loop_exit + + moveq.l #0,d7 + moveq.l #0,d3 ; flag for stitching -- if set, must not trigger new note + ; enters with d4 = -1, meaning no first note pos yet + + move.w pcd_inst_num_w(a5),d1 + add.w d1,d1 + add.w d1,d1 + add.w #sv_inst_patterns_table,d1 + movea.l -4(a6,d1.w),a0 + + add.w d0,a0 + add.w d0,a0 + add.w d0,a0 + +.inst_pat_loop + IFNE PRETRACKER_PARANOIA_MODE + moveq.l #0,d2 ; default to not stitched + move.b (a0)+,d1 ; pdb_pitch_ctrl get pitch byte + move.b d1,d6 + bpl.s .inst_note_is_not_stitched ; means that note is stitched + + tst.w d4 + bpl.s .inst_no_update_first_note + move.w d0,d4 ; position of first note before stitching +.inst_no_update_first_note + moveq.l #1,d2 ; next note will be fetched immediately +.inst_note_is_not_stitched + ELSE + move.b (a0)+,d1 ; pdb_pitch_ctrl get pitch byte + move.b d1,d6 + smi d2 ; note stitched? + ;neg.b d2 + ENDC + + tst.b d3 + bne.s .skippitchloading + andi.w #$3F,d1 + beq.s .skippitchloading ; no new note + subq.w #1,d1 + lsl.w #4,d1 + move.w d1,pcd_inst_note_pitch_w(a5) + and.w #1<<6,d6 + sne pcd_inst_pitch_pinned_b(a5) + IFEQ PRETRACKER_FASTER_CODE + neg.b pcd_inst_pitch_pinned_b(a5) ; only to be state binary compatible + ENDC +.skippitchloading + moveq.l #15,d6 + and.b (a0)+,d6 ; pdb_effect_cmd command number + add.w d6,d6 + moveq.l #0,d5 + move.b (a0)+,d5 ; pdb_effect_data command parameter byte + move.w .inst_command_jmptable(pc,d6.w),d3 + jmp .inst_command_jmptable(pc,d3.w) + +.inst_command_jmptable + dc.w .inst_select_wave-.inst_command_jmptable + dc.w .inst_slide_up-.inst_command_jmptable + dc.w .inst_slide_down-.inst_command_jmptable + dc.w .inst_adsr-.inst_command_jmptable + dc.w .inst_select_wave-.inst_command_jmptable + dc.w .inst_nop-.inst_command_jmptable + dc.w .inst_nop-.inst_command_jmptable + dc.w .inst_nop-.inst_command_jmptable + dc.w .inst_nop-.inst_command_jmptable + dc.w .inst_nop-.inst_command_jmptable + dc.w .inst_vol_slide-.inst_command_jmptable + dc.w .inst_jump_to_step-.inst_command_jmptable + dc.w .inst_set_volume-.inst_command_jmptable + dc.w .inst_nop-.inst_command_jmptable + dc.w .inst_use_pat_arp-.inst_command_jmptable + dc.w .inst_set_speed-.inst_command_jmptable + +; d0 = current step / next step +; d5 = command parameter data / scratch +; d2 = note stitched flag +; d6 = scratch +; ---------------------------------------- +.inst_select_wave + subq.w #1,d5 + cmp.w #MAX_WAVES,d5 + bhs .inst_cmd_cont_next + add.w d5,d5 + add.w d5,d5 + cmp.w pcd_inst_wave_num_w(a5),d5 + beq .inst_cmd_cont_next + move.w d5,pcd_inst_wave_num_w(a5) + move.l sv_waveinfo_table(a6,d5.w),a3 + move.l a3,pcd_waveinfo_ptr(a5) + + move.b pcd_channel_mask_b(a5),d3 + move.b d3,pcd_out_trg_b(a5) + or.b d3,pv_trigger_mask_w+1(a4) + + move.l pv_wave_sample_table(a4,d5.w),a1 + tst.w d6 + bne.s .inst_select_wave_nosync + + moveq.l #0,d3 + move.w wi_loop_offset_w(a3),d6 ; is unlikely 32768 + tst.w wi_subloop_len_w(a3) + bne.s .inst_set_wave_has_subloop + + adda.w d6,a1 ; add loop offset + + move.w wi_chipram_w(a3),d5 + sub.w d6,d5 + ;cmp.w #1,d5 ; not necessary as increases in steps of 2 + bhi.s .inst_set_wave_has_min_length + moveq.l #2,d5 +.inst_set_wave_has_min_length + move.w d5,pcd_out_len_w(a5) + + moveq.l #-1,d3 +.inst_set_wave_has_subloop + move.w d3,pcd_out_lof_w(a5) + move.l a1,pcd_out_ptr_l(a5) + + move.w #1,pcd_inst_ping_pong_s_w(a5) + moveq.l #0,d5 + move.b wi_subloop_wait_b(a3),d5 + addq.w #1,d5 + move.w d5,pcd_inst_subloop_wait_w(a5) + + move.w d6,pcd_inst_loop_offset_w(a5) + bra .inst_cmd_cont_next + +; ---------------------------------------- +.inst_select_wave_nosync + move.w wi_chipram_w(a3),d5 + moveq.l #0,d3 + tst.w wi_subloop_len_w(a3) + bne.s .inst_set_wave_ns_has_subloop + + move.w wi_loop_offset_w(a3),d6 + adda.w d6,a1 + + sub.w d6,d5 + ;cmp.w #1,d5 ; not necessary as increases in steps of 2 + bhi.s .inst_set_wave_ns_has_min_length + moveq.l #2,d5 +.inst_set_wave_ns_has_min_length + move.w d5,pcd_out_len_w(a5) + + moveq.l #-1,d3 +.inst_set_wave_ns_has_subloop + move.w d3,pcd_out_lof_w(a5) + move.l a1,pcd_out_ptr_l(a5) + + move.w pcd_inst_loop_offset_w(a5),d6 + cmp.w d6,d5 + bhs.s .inst_set_wave_ns_keep_pp + move.w #1,pcd_inst_ping_pong_s_w(a5) +.inst_set_wave_ns_keep_pp + moveq.l #0,d5 + move.w d5,pcd_inst_subloop_wait_w(a5) + + sub.w wi_subloop_step_w(a3),d6 + move.w d6,pcd_inst_loop_offset_w(a5) + bra .inst_cmd_cont_next + +; ---------------------------------------- +.inst_slide_down + neg.w d5 +.inst_slide_up + move.w d5,pcd_inst_pitch_slide_w(a5) + bra .inst_cmd_cont_next + +; ---------------------------------------- +.inst_adsr + subq.w #1,d5 + beq.s .inst_adsr_release + subq.w #1,d5 + bne .inst_cmd_cont_next + ; d5.l is zero + move.w d5,pcd_adsr_phase_w(a5) + move.w d5,pcd_adsr_volume_w(a5) + bra .inst_cmd_cont_next + +.inst_adsr_release + move.w pcd_adsr_volume_w(a5),d5 + asr.w #6,d5 ; FIXME lsr? + move.w d5,pcd_adsr_vol64_w(a5) + moveq.l #16,d6 + move.w d6,pcd_adsr_pos_w(a5) + sub.w d5,d6 + lsr.w #1,d6 + add.b pcd_adsr_release_b(a5),d6 + move.b d6,pcd_adsr_phase_speed_b(a5) + move.w #3,pcd_adsr_phase_w(a5) + bra.s .inst_cmd_cont_next + +; ---------------------------------------- +.inst_vol_slide + moveq.l #15,d3 + and.w d5,d3 + beq.s .inst_vol_slide_up + ; NOTE: Changed behaviour: using d3 instead of d5 + ; if both lower and upper were specified, this + ; probably led to a drastic decrease of volume. + neg.w d3 + move.b d3,pcd_inst_vol_slide_b(a5) + bra.s .inst_cmd_cont_next + +.inst_vol_slide_up + lsr.b #4,d5 + move.b d5,pcd_inst_vol_slide_b(a5) + bra.s .inst_cmd_cont_next + +; ---------------------------------------- +.inst_jump_to_step + cmp.w d0,d5 + bge.s .inst_cmd_cont_next ; only backward jumps allowed (?) + IFNE PRETRACKER_PARANOIA_MODE + ; this stuff is PARANOIA + tst.b d4 + bmi.s .inst_jump_to_step_doit ; we did not have a stitched note before + cmp.b d3,d4 + ble .inst_cmd_cont_next ; we are jumping back to the stitched note, ignore +.inst_jump_to_step_doit + ENDC + move.w d5,d0 + tst.b d7 ; check if we had jumped before + bne.s .inst_we_were_stitched + IFNE PRETRACKER_PARANOIA_MODE + moveq.l #-1,d4 ; mark as no first stitch pos + ENDC + + move.w pcd_inst_num_w(a5),d1 + add.w d1,d1 + add.w d1,d1 + add.w #sv_inst_patterns_table,d1 + movea.l -4(a6,d1.w),a0 + + add.w d5,a0 + add.w d5,d5 + add.w d5,a0 + + bra.s .inst_fetch_next +.inst_we_were_stitched + move.b pcd_inst_speed_stop_b(a5),d2 + bra.s .inst_cont_from_nasty_double_jump + +; ---------------------------------------- +.inst_set_volume + cmp.w #MAX_VOLUME,d5 + ble.s .inst_set_volume_nomax + moveq.l #MAX_VOLUME,d5 +.inst_set_volume_nomax + move.w d5,pcd_inst_vol_w(a5) + bra.s .inst_cmd_cont_next + +; ---------------------------------------- +.inst_use_pat_arp + moveq.l #3,d3 + and.w d5,d3 + beq.s .inst_use_pat_arp_play_base + lsr.w #4,d5 + beq.s .inst_use_pat_arp_skip_empty + subq.w #1,d5 + bne.s .inst_cmd_cont_next ; illegal high nibble (only 0/1 allowed) + + ; pick arp note + move.b pcd_arp_notes_l-1(a5,d3.w),d3 + + ; play base note +.inst_use_pat_arp_set + lsl.w #4,d3 +.inst_use_pat_arp_play_base + move.w d3,pcd_inst_sel_arp_note_w(a5) + bra.s .inst_cmd_cont_next + +.inst_use_pat_arp_skip_empty + ; pick arp note, if it's 0, skip it + move.b pcd_arp_notes_l-1(a5,d3.w),d3 + bne.s .inst_use_pat_arp_set + + addq.w #1,d0 + bra.s .inst_fetch_next + +; ---------------------------------------- +.inst_set_speed + tst.w d5 + bne.s .inst_set_speed_nostop + st d5 +.inst_set_speed_nostop + move.b d5,pcd_inst_speed_stop_b(a5) + +; ---------------------------------------- +.inst_nop +.inst_cmd_cont_next + addq.w #1,d0 + tst.b d2 + beq.s .inst_pat_loop_exit2 + ; d2 != 0 in this case, hence d3 will be set +.inst_fetch_next + moveq.l #1,d7 ; mark that we are in at least next iteration + move.b d2,d3 ; mark stitching + cmp.b pcd_inst_pattern_steps_b(a5),d0 + blo .inst_pat_loop + +.inst_pat_loop_exit + st d2 +.inst_pat_loop_exit2 + add.b pcd_inst_speed_stop_b(a5),d2 +.inst_cont_from_nasty_double_jump + move.b d2,pcd_inst_line_ticks_b(a5) + move.b d0,pcd_inst_step_pos_b(a5) ; update inst step pos + +.inst_still_ticking + tst.b pcd_inst_wave_num_w+1(a5) + bpl.s .inst_wave_selected + +.inst_no_wave_selected + moveq.l #0,d3 + move.w d3,pcd_inst_wave_num_w(a5) ; FIXME why set to wave 0? just asking, because this is zero based + move.l sv_waveinfo_ptr(a6),a3 + move.l a3,pcd_waveinfo_ptr(a5) + + move.b pcd_channel_mask_b(a5),d0 + move.b d0,pcd_out_trg_b(a5) + or.b d0,pv_trigger_mask_w+1(a4) + + tst.w wi_subloop_len_w(a3) + bne.s .inst_nowave_has_subloop + + move.w wi_loop_offset_w(a3),d5 + move.l pv_wave_sample_table(a4),a1 + adda.w d5,a1 + move.l a1,pcd_out_ptr_l(a5) + + move.w wi_chipram_w(a3),d0 + move.w d0,d6 + subq.w #1,d6 + cmp.w d4,d6 + ble.s .lbC00118E + sub.w d5,d0 + bra.s .lbC000F48 +.lbC00118E + moveq.l #2,d0 +.lbC000F48 + move.w d0,pcd_out_len_w(a5) + subq.w #1,d3 + bra.s .inst_set_no_lof + +.inst_nowave_has_subloop + move.l pv_wave_sample_table(a4),pcd_out_ptr_l(a5) + + move.w wi_loop_offset_w(a3),d4 +.inst_set_no_lof + move.w d3,pcd_out_lof_w(a5) + moveq.l #0,d0 + move.b wi_subloop_wait_b(a3),d0 + addq.w #1,d0 + move.w d0,pcd_inst_subloop_wait_w(a5) + + move.w d4,pcd_inst_loop_offset_w(a5) + move.w #1,pcd_inst_ping_pong_s_w(a5) + +.inst_wave_selected + cmpi.b #$FF,d2 + beq.s .inst_pat_loop_exit3 + subq.b #1,d2 + move.b d2,pcd_inst_line_ticks_b(a5) + +.inst_no_inst_active +.inst_pat_loop_exit3 + move.w wi_subloop_len_w(a3),d3 + +; ---------------------------------------- + +; expects d2 = inst num +; a5 = channel + + move.w pcd_inst_vol_w(a5),d1 + moveq.l #0,d2 + move.b pcd_new_inst_num_b(a5),d2 + beq.s .dont_load_instrument + +.loadinstrument + move.b d1,pcd_loaded_inst_vol_b(a5) + move.l uii_vibrato_delay(a2),pcd_vibrato_delay_w(a5) ; and uii_vibrato_depth + ;move.w uii_vibrato_delay(a2),pcd_vibrato_delay_w(a5) + ;move.w uii_vibrato_depth(a2),pcd_vibrato_depth_w(a5) + + move.l uii_vibrato_speed(a2),pcd_vibrato_speed_w(a5) ; and uii_adsr_release + ;move.w uii_vibrato_speed(a2),pcd_vibrato_speed_w(a5) + ;move.b uii_adsr_release(a2),pcd_adsr_release_b(a5) + + moveq.l #0,d2 + move.l d2,pcd_adsr_phase_w(a5) ; and pcd_adsr_volume_w + ;move.w d2,pcd_adsr_phase_w(a5) + ;move.w d2,pcd_adsr_volume_w(a5) + + move.w d2,pcd_vibrato_pos_w(a5) + move.b d2,pcd_new_inst_num_b(a5) + +.adsr_attack + add.w uii_adsr_attack(a2),d2 + cmpi.w #MAX_VOLUME<<4,d2 + blt .adsr_done + +.adsr_do_decay + move.w #MAX_VOLUME<<4,d2 + move.w #1,pcd_adsr_phase_w(a5) + move.b uii_adsr_decay+1(a2),pcd_adsr_phase_speed_b(a5) + bra .adsr_done + +.dont_load_instrument + move.w pcd_adsr_volume_w(a5),d2 + move.w pcd_adsr_phase_w(a5),d4 + beq.s .adsr_attack + subq.w #1,d4 + beq.s .adsr_decay + subq.w #1,d4 + beq .adsr_sustain + +.adsr_release + move.w pcd_adsr_pos_w(a5),d4 + add.w pcd_adsr_vol64_w(a5),d4 + move.w d4,pcd_adsr_pos_w(a5) + cmpi.w #15,d4 + ble.s .adsr_sustain + + ; release? + moveq.l #0,d5 + move.b pcd_adsr_phase_speed_b(a5),d5 + cmpi.b #$8E,d5 + bhi.s .lbC001142 + addq.b #1,pcd_adsr_phase_speed_b(a5) + + add.w d5,d5 + lea pre_roll_off_table(pc),a1 + move.w (a1,d5.w),d5 + bra.s .lbC001148 + +.adsr_decay + moveq.l #0,d4 + move.b pcd_adsr_phase_speed_b(a5),d4 + cmpi.b #$8E,d4 + bhi.s .adsr_absurd_long_decay + move.b d4,d5 + addq.b #1,d5 + add.w d4,d4 + lea pre_roll_off_table(pc),a1 + move.w (a1,d4.w),d4 + bra.s .adsr_decay_cont +.adsr_absurd_long_decay + moveq.l #2,d4 ; FIXME I guess this should be 1, if I look at the roll-off table + moveq.l #-$71,d5 +.adsr_decay_cont + move.b d5,pcd_adsr_phase_speed_b(a5) + sub.w d4,d2 + move.w d2,d4 + move.w uii_adsr_sustain(a2),d2 + cmp.w d4,d2 + bge.s .adsr_enter_sustain + move.w d4,d2 + bra.s .adsr_done + +.adsr_enter_sustain + move.w #2,pcd_adsr_phase_w(a5) + bra.s .adsr_done + +.lbC001142 + moveq.l #2,d5 + move.b #-$71,pcd_adsr_phase_speed_b(a5) +.lbC001148 + sub.w d5,d2 + bpl.s .adsr_noclip_vol + moveq.l #0,d2 +.adsr_noclip_vol + sub.w #16,d4 + move.w d4,pcd_adsr_pos_w(a5) +.adsr_sustain + +.adsr_done + move.w d2,pcd_adsr_volume_w(a5) + lsr.w #4,d2 + +; ---------------------------------------- +; return from .loadinstrument + move.b pcd_note_off_delay_b(a5),d4 + beq.s .dont_release_note + subq.b #1,d4 + move.b d4,pcd_note_off_delay_b(a5) + bne.s .dont_release_note + ; cut off note + clr.w pcd_adsr_volume_w(a5) + move.w #3,pcd_adsr_phase_w(a5) + +.dont_release_note + IFNE PRETRACKER_VOLUME_TABLE + lea pv_volume_table(a4),a1 + lsl.w #7,d2 + or.b d1,d2 + move.b (a1,d2.w),d1 + lsl.w #7,d1 + or.b pcd_pat_vol_b(a5),d1 + move.b (a1,d1.w),pcd_out_vol_b(a5) + ELSE + mulu d2,d1 + lsr.w #6,d1 + + moveq.l #0,d2 + move.b pcd_pat_vol_b(a5),d2 + mulu d1,d2 + lsr.w #6,d2 + move.b d2,pcd_out_vol_b(a5) + ENDC + +; ---------------------------------------- +; wave looping (FIXME this needs some serious tidying) + + move.w wi_subloop_step_w(a3),d2 + moveq.l #0,d1 + move.b pcd_wave_offset_b(a5),d1 + ; FIXME can we merge this code path + tst.w d3 + beq .lbC000D8E + + tst.b d1 + beq.s .no_wave_offset + tst.b wi_allow_9xx_b(a3) + beq.s .no_wave_offset + + lsl.w #7,d1 + move.w d1,pcd_inst_loop_offset_w(a5) + clr.b pcd_wave_offset_b(a5) + + move.w pcd_inst_ping_pong_s_w(a5),d4 + ble.s .lbC001178 + sub.w d2,d1 + bra.s .lbC000486 + +.no_wave_offset + move.w pcd_inst_subloop_wait_w(a5),d1 + subq.w #1,d1 + bls.s .lbC00110C + move.w d1,pcd_inst_subloop_wait_w(a5) + + move.w pcd_inst_loop_offset_w(a5),d1 + move.w d3,pcd_out_len_w(a5) + move.w d1,pcd_out_lof_w(a5) + + ;moveq.l #0,d1 + move.w pcd_inst_wave_num_w(a5),d1 + move.l pv_wave_sample_table(a4,d1.w),pcd_out_ptr_l(a5) + bra .loop_handling_done + +.lbC00110C + move.w pcd_inst_ping_pong_s_w(a5),d4 + move.w pcd_inst_loop_offset_w(a5),d1 + bra.s .lbC00048A + +.lbC001178 + add.w d2,d1 +.lbC000486 + move.w d1,pcd_inst_loop_offset_w(a5) +.lbC00048A + moveq.l #0,d5 + move.b wi_subloop_wait_b(a3),d5 ; FIXME why is this not increased by one here? + move.w d5,pcd_inst_subloop_wait_w(a5) + tst.w d4 + ble.s .lbC0010A0 + add.w d2,d1 + move.w d3,d4 + add.w d1,d4 + + move.w wi_loop_end_w(a3),d2 + + cmp.w d1,d2 + bhs.s .is_not_past_loop_end + move.w wi_chipram_w(a3),d2 +.is_not_past_loop_end + sub.w d4,d2 + bhi.s .lbC0004C6 + add.w d2,d1 + move.w d1,pcd_inst_loop_offset_w(a5) + move.w #-1,pcd_inst_ping_pong_s_w(a5) + move.w d1,d4 + tst.w d2 + bne.s .done_lof_calc + bra.s .lbC000C66 + +.lbC0010A0 + sub.w d2,d1 + + move.w wi_loop_start_w(a3),d2 + + move.w d2,d4 + move.w d2,d6 + sub.w d1,d6 + bpl.s .do_loop_forward +.lbC0004C6 + move.w d1,pcd_inst_loop_offset_w(a5) + move.w d1,d4 + bra.s .done_lof_calc + +.do_loop_forward + move.w d2,pcd_inst_loop_offset_w(a5) + move.w #1,pcd_inst_ping_pong_s_w(a5) + tst.w d6 + bne.s .done_lof_calc +.lbC000C66 + subq.w #1,d5 + move.w d5,pcd_inst_subloop_wait_w(a5) + +.done_lof_calc + move.w d3,pcd_out_len_w(a5) + move.w d4,pcd_out_lof_w(a5) + + move.w pcd_inst_wave_num_w(a5),d1 + move.l pv_wave_sample_table(a4,d1.w),pcd_out_ptr_l(a5) + bra.s .loop_handling_done + + ; FIXME can we merge this code path with the one at lbC0004EA +.lbC000D8E + tst.b d1 + beq.s .loop_handling_done + tst.b wi_allow_9xx_b(a3) + beq.s .loop_handling_done + + move.b pcd_channel_mask_b(a5),d3 + move.b d3,pcd_out_trg_b(a5) + or.b d3,pv_trigger_mask_w+1(a4) + + lsl.w #7,d1 + move.l d1,d3 + + move.w pcd_inst_wave_num_w(a5),d1 + move.l pv_wave_sample_table(a4,d1.w),d1 + + add.l d3,d1 + move.l d1,pcd_out_ptr_l(a5) + + move.w wi_chipram_w(a3),d2 + move.w d2,d4 + subq.w #1,d4 + sub.w d3,d2 + cmp.w d3,d4 + bgt.s .is_not_oneshot + moveq.l #2,d2 +.is_not_oneshot + move.w d2,pcd_out_len_w(a5) + move.w #$FFFF,pcd_out_lof_w(a5) + clr.b pcd_wave_offset_b(a5) + + ; position of merging code + ; FIXME can we merge this code path? +.loop_handling_done + +; ---------------------------------------- +; pitch handling + move.w pcd_inst_pitch_w(a5),d0 + sub.w #$10,d0 + tst.b pcd_inst_pitch_pinned_b(a5) + bne.s .pitch_pinned +.pitch_not_pinned + add.w pcd_inst_sel_arp_note_w(a5),d0 + add.w pcd_inst_curr_port_pitch_w(a5),d0 + sub.w #$10,d0 +.pitch_pinned + add.w pcd_inst_note_pitch_w(a5),d0 + +; ---------------------------------------- +; vibrato processing + move.b pcd_vibrato_delay_w+1(a5),d1 + beq.s .vibrato_already_active + subq.b #1,d1 + move.b d1,pcd_vibrato_delay_w+1(a5) + bne.s .vibrato_still_delayed + + ; activate vibrato + move.w pcd_vibrato_depth_w(a5),d4 + move.w d4,d2 + muls pcd_vibrato_speed_w(a5),d2 ; i don't quite get this... + asr.w #4,d2 + move.w d2,pcd_vibrato_speed_w(a5) + bra.s .vibrato_cont_act + +.vibrato_already_active + move.w pcd_vibrato_speed_w(a5),d2 + beq.s .vibrato_still_delayed ; no speed -- skip stuff + move.w pcd_vibrato_depth_w(a5),d4 +.vibrato_cont_act + move.w d2,d1 + add.w pcd_vibrato_pos_w(a5),d1 + cmp.w d1,d4 + blt.s .vibrato_flipit + neg.w d4 + cmp.w d1,d4 + ble.s .vibrato_cont +.vibrato_flipit + neg.w d2 + move.w d2,pcd_vibrato_speed_w(a5) + move.w d4,d1 +.vibrato_cont + move.w d1,pcd_vibrato_pos_w(a5) + + asr.w #3,d1 + add.w d1,d0 +.vibrato_still_delayed + +; ---------------------------------------- + + move.w pcd_out_len_w(a5),d3 + cmpi.w #$219,d0 + ble .noclippitchhigh + move.w #$231,d6 ; That's probably B-3+1, mapping to period $71 (although $7c is the last safe value) + btst #2,wi_flags_b(a3) + beq .noclippitchlow2 + + ; select high pitch version of the sample + moveq.l #0,d2 + move.w wi_chipram_w(a3),d2 + move.w d0,d5 + sub.w #$219,d5 + lsr.w #6,d5 + lea pre_octave_select_table(pc),a1 + moveq.l #0,d1 + move.b (a1,d5.w),d1 + move.w pcd_out_lof_w(a5),d7 + addq.w #1,d7 ; compare to $ffff + beq.s .has_no_loop_offset + subq.w #1,d7 + lsr.w d1,d7 + move.w d7,pcd_out_lof_w(a5) + lsr.w d1,d3 + move.w d3,pcd_out_len_w(a5) + bra.s .lbC0005C0 + +.has_no_loop_offset + tst.b pcd_out_trg_b(a5) + beq.s .no_retrigger_new + + move.w pcd_inst_wave_num_w(a5),d7 + movea.l pv_wave_sample_table(a4,d7.w),a3 + + move.l pcd_out_ptr_l(a5),d4 + sub.l a3,d4 + move.w d3,d6 + add.w d4,d6 + + move.w d2,d7 + sub.w d6,d7 + cmp.w d7,d3 + bcc.s .fix_sample_loop + moveq.l #2,d3 + bra.s .cont_after_one_shot + +.fix_sample_loop + add.w d6,d3 + sub.w d2,d3 + lsr.w d1,d3 + +.cont_after_one_shot + move.w d3,pcd_out_len_w(a5) + + lsr.w d1,d4 + add.l a3,d4 + move.l d4,pcd_out_ptr_l(a5) + +.lbC0005C0 + subq.b #1,d1 + bmi.s .is_normal_octave + ; find offset in sample buffer for the right octave + moveq.l #0,d4 +.movetoloopposloop + add.l d2,d4 + lsr.w #1,d2 + dbra d1,.movetoloopposloop + add.l d4,pcd_out_ptr_l(a5) + +.no_retrigger_new +.is_normal_octave + moveq.l #0,d1 + move.b pre_octave_note_offset_table-pre_octave_select_table(a1,d5.w),d1 + add.w d1,d1 + add.w d1,d1 + sub.w d1,d0 + cmpi.w #$231,d0 + ble.s .noclippitchhigh + move.w #$231,d0 +.noclippitchhigh + tst.w d0 + bge.s .noclippitchlow + moveq.l #0,d0 +.noclippitchlow + move.w d0,d6 +.noclippitchlow2 + tst.b pcd_out_trg_b(a5) + beq.s .wasnottriggered + moveq.l #0,d0 + move.w pcd_out_lof_w(a5),d0 + addq.w #1,d0 ; compare to $ffff + beq.s .hasnoloop2 + subq.w #1,d0 + add.l d0,pcd_out_ptr_l(a5) + clr.w pcd_out_lof_w(a5) +.wasnottriggered +.hasnoloop2 + cmp.w pcd_last_trigger_pos_w(a5),d3 + beq.s .hassamesampos + move.w d3,pcd_last_trigger_pos_w(a5) + move.b pcd_channel_mask_b(a5),d3 + move.b d3,pcd_out_trg_b(a5) + or.b d3,pv_trigger_mask_w+1(a4) +.hassamesampos + add.w d6,d6 + move.w pv_period_table(a4,d6.w),pcd_out_per_w(a5) + +; ---------------------------------------- +; track delay handling + + move.b pcd_track_delay_steps_b(a5),d0 + beq .incrementchannel ; no track delay + + cmp.b #NUM_CHANNELS-1,pcd_channel_num_b(a5) ; last channel processed? + beq .updatechannels ; no track delay for last channel + + ; handle track delay + cmpi.b #$FF,d0 + beq.s .clear_track_delay + + ; advance and wrap offset + move.b pcd_SIZEOF+pcd_track_delay_offset_b(a5),d1 + addq.b #1,d1 + andi.w #$1F,d1 + move.b d1,pcd_SIZEOF+pcd_track_delay_offset_b(a5) + + move.w d1,d2 + lsl.w #4,d2 + lea (a5,d2.w),a1 + lea pcd_SIZEOF+pcd_track_delay_buffer(a1),a3 + move.l pcd_out_base+0(a5),(a3)+ ; ocd_sam_ptr + move.l pcd_out_base+4(a5),(a3)+ ; ocd_length/ocd_loop_offset + move.l pcd_out_base+8(a5),(a3)+ ; ocd_period/ocd_volume/ocd_trigger + ;move.l pcd_out_base+12(a5),(a3)+ ; this is never used + + move.b pcd_SIZEOF+pcd_channel_mask_b(a5),d2 + tst.b -(a3) + bne.s .copy_trigger_for_delayed_channel + tst.b pcd_SIZEOF+pcd_track_delay_steps_b(a5) + bne.s .dont_trigger_track_delay_first_note + move.b d2,(a3) ; trigger note (ocd_trigger) +.copy_trigger_for_delayed_channel + or.b d2,pv_trigger_mask_w+1(a4) +.dont_trigger_track_delay_first_note + + IFNE PRETRACKER_VOLUME_TABLE + lea pv_volume_table(a4),a1 + move.b pcd_track_delay_vol16_b(a5),-(sp) + move.w (sp)+,d4 + clr.b d4 + add.w d4,d4 + move.b -(a3),d4 ; ocd_volume + move.b (a1,d4.w),(a3)+ + ELSE + moveq.l #0,d4 + move.b -(a3),d4 ; ocd_volume + move.b pcd_track_delay_vol16_b(a5),d2 + ext.w d2 + mulu d4,d2 ; apply track delay volume + lsr.w #4,d2 + move.b d2,(a3)+ ; fix volume + ENDC + + move.b d0,pcd_SIZEOF+pcd_track_delay_steps_b(a5) + + sub.b d0,d1 + bpl.s .no_wrap_trd_pos + addi.b #$20,d1 +.no_wrap_trd_pos + move.b d1,d0 + ext.w d0 + + IFNE PRETRACKER_DUBIOUS_PITCH_SHIFT_FOR_DELAYED_TRACK + moveq.l #7,d4 + and.w d4,d1 + lea pre_minus4plus4_table(pc),a1 + move.b (a1,d1.w),d1 + ext.w d1 + ENDC + bra.s .load_track_data_from_buffer + +.clear_track_delay + moveq.l #0,d1 + move.b d1,pcd_track_delay_steps_b(a5) + move.b d1,pcd_SIZEOF+pcd_pat_vol_b(a5) + move.b d1,pcd_SIZEOF+pcd_track_delay_steps_b(a5) + st pcd_SIZEOF+pcd_track_delay_offset_b(a5) + + moveq.l #$1f,d0 ; load from last buffer + +.load_track_data_from_buffer + lea pcd_SIZEOF(a5),a5 ; skip the channel we applied track delay to + lsl.w #4,d0 + lea (a5,d0.w),a0 + lea pcd_out_base(a5),a3 + lea pcd_track_delay_buffer(a0),a1 + move.l (a1)+,(a3)+ + move.l (a1)+,(a3)+ + move.l (a1)+,(a3)+ + ;move.l (a1)+,(a3)+ ; this is never used + + clr.b pcd_track_delay_buffer+ocd_volume(a0) + + IFNE PRETRACKER_DUBIOUS_PITCH_SHIFT_FOR_DELAYED_TRACK + ; FIXME this seems odd! Why modulate the period by the distance? + move.w pcd_out_base+ocd_period(a5),d2 + move.w d1,d0 + muls d2,d0 + lsl.l #4,d0 + swap d0 + add.w d0,d2 + move.w d2,pcd_out_base+ocd_period(a5) + ENDC + +.incrementchannel + lea pcd_SIZEOF(a5),a5 + cmp.b #NUM_CHANNELS-1,pcd_channel_num_b-pcd_SIZEOF(a5) + bne .inst_chan_loop + +; ---------------------------------------- +.updatechannels + ; so this changed a lot from the original routine + move.w pv_trigger_mask_w(a4),d2 + + IFNE PRETRACKER_COPPER_OUTPUT + move.l pv_copperlist_ptr(a4),d0 + beq .skipcopperlist + move.l d0,a5 + move.b d2,1*4+3(a5) ; dmacon + move.b d2,(1+1+1+5*NUM_CHANNELS)*4+3(a5) ; dmacon after wait, dmacon, wait, 20 writes + + lea pv_channeldata+pcd_out_base(a4),a0 + move.l pv_sample_buffer_ptr(a4),d3 + moveq.l #0,d5 + move.w d5,pv_trigger_mask_w(a4) + moveq.l #-1,d1 + lea 3*4+2(a5),a1 + lea (1+1+1+5*NUM_CHANNELS+1+1)*4+2(a5),a2 ; wait, dmacon, wait, 20 writes, dmacon, wait + moveq.l #NUM_CHANNELS-1,d7 +.checkchan + moveq.l #0,d2 + move.w ocd_loop_offset(a0),d2 + cmp.w d1,d2 + bne.s .is_looping_sample + tst.b ocd_trigger(a0) + beq.s .one_shot_clear_loop + move.b d5,ocd_trigger(a0) + move.l ocd_sam_ptr(a0),d0 + move.l d3,d6 ; set loop start + move.w ocd_length(a0),d4 + lsr.w #1,d4 + move.w d4,2*4(a1) ; ac_len + moveq.l #1,d4 + bra.s .setptrvolper +.one_shot_clear_loop + move.l d3,d6 + move.l d3,d0 + moveq.l #1,d4 + move.w d4,2*4(a1) ; ac_len + bra.s .setptrvolper + +.is_looping_sample + move.l ocd_sam_ptr(a0),d0 + add.l d2,d0 + move.l d0,d6 + + move.w ocd_length(a0),d4 + lsr.w #1,d4 + move.w d4,2*4(a1) ; ac_len + tst.b ocd_trigger(a0) + beq.s .setptrvolper + move.b d5,ocd_trigger(a0) + sub.l d2,d6 +.setptrvolper + move.w d0,1*4(a1) ; ac_ptr (lo) + swap d0 + move.w d0,(a1) ; ac_ptr (hi) + move.w ocd_period(a0),3*4(a1) + move.b ocd_volume(a0),4*4+1(a1) + move.w d6,1*4(a2) ; ac_ptr (lo) + swap d6 + move.w d6,(a2) ; ac_ptr (hi) + move.w d4,2*4(a2) ; ac_len + + lea pcd_SIZEOF(a0),a0 + lea 5*4(a1),a1 + lea 3*4(a2),a2 + dbra d7,.checkchan + +.skipcopperlist + ELSE + lea $dff000,a5 + + ; turn channels off and remember raster position + move.w d2,dmacon(a5) ; turn dma channels off + move.w vhposr(a5),d5 + add.w #4<<8,d5 ; target rasterpos + + ; in the meanwhile we can update both channels that + ; - need triggering by setting the new start and length + ; - need updating of loop offset only + ; update volume and period in any case + lea pv_channeldata+pcd_out_base(a4),a0 + lea aud0(a5),a1 + move.l pv_sample_buffer_ptr(a4),d3 + moveq.l #0,d6 + move.w d6,pv_trigger_mask_w(a4) + moveq.l #-1,d1 + moveq.l #NUM_CHANNELS-1,d7 +.checkchan + tst.b ocd_trigger(a0) + beq.s .updateloop + move.b d6,ocd_trigger(a0) + ; set start and length of the new sample + move.w ocd_length(a0),d0 + lsr.w #1,d0 + move.w d0,ac_len(a1) + move.l ocd_sam_ptr(a0),ac_ptr(a1) + bra.s .setvolperchan +.updateloop + ; just update loop offset if looping + moveq.l #0,d0 + move.w ocd_loop_offset(a0),d0 + cmp.w d1,d0 + beq.s .setvolperchan + add.l ocd_sam_ptr(a0),d0 + move.l d0,ac_ptr(a1) +.setvolperchan + move.b ocd_volume(a0),ac_vol+1(a1) + move.w ocd_period(a0),ac_per(a1) + lea pcd_SIZEOF(a0),a0 + lea ac_SIZEOF(a1),a1 + dbra d7,.checkchan + + tst.w d2 + beq.s .skiprasterwait ; if no channel needed triggering, we are done! + +.rasterwait1 + cmp.w vhposr(a5),d5 + bgt.s .rasterwait1 + + or.w #DMAF_SETCLR,d2 + move.w d2,dmacon(a5) ; enable triggered channels + add.w #4<<8,d5 ; target rasterpos + +.rasterwait2 + cmp.w vhposr(a5),d5 + bgt.s .rasterwait2 + + lea pv_channeldata+pcd_out_base(a4),a0 + lea aud(a5),a1 +.chanloop + lsr.b #1,d2 + bcc.s .nosetloopchan + moveq.l #0,d0 + move.w ocd_loop_offset(a0),d0 + cmp.w d1,d0 + beq.s .setchan_no_loop2 + add.l ocd_sam_ptr(a0),d0 + bra.s .keepchanrunning2 +.setchan_no_loop2 + move.l d3,d0 + move.w #1,ac_len(a1) +.keepchanrunning2 + move.l d0,ac_ptr(a1) +.nosetloopchan + lea pcd_SIZEOF(a0),a0 + lea ac_SIZEOF(a1),a1 + tst.b d2 + bne.s .chanloop + +.skiprasterwait + ENDC + + IFNE PRETRACKER_DONT_TRASH_REGS + movem.l (sp)+,d2-d7/a2-a6 + ENDC + rts + +; ---------------------------------------- + +pre_update_pat_line_counter + move.b pv_pat_speed_b(a4),d1 + cmpi.b #MAX_SPEED,d1 + bls.s .pat_set_speed_no_shuffle + btst #0,pv_pat_curr_row_b(a4) + beq.s .pat_set_even_speed + andi.b #15,d1 + bra.s .pat_set_speed_no_shuffle +.pat_set_even_speed + lsr.b #4,d1 +.pat_set_speed_no_shuffle + move.b d1,pv_pat_line_ticks_b(a4) + rts + +;-------------------------------------------------------------------- +; table data currently about 594 bytes + +; I assume this is a log table for freq distances within an octave +pre_log12_table: + dc.b $400000/$8000,$400000/$871D,$400000/$8F2F,$400000/$97B7,$400000/$9FC4,$400000/$A9DE + dc.b $400000/$B505,$400000/$BF49,$400000/$CB31,$400000/$D645,$400000/$E215,$400000/$F1A0 + +; linear then steep quadratic slope +pre_vib_speed_table: + dc.b 2,3,4,5,6,7,8,9,10,11,12,13,14,20,40,80 + +; linear (a bit wonky), then a bit quadratic, then steep +pre_vib_depth_table: + dc.b 0,8,9,10,11,12,13,14,18,20,28,40,50,70,160,255 + +; linear then almost quadratic +pre_vib_delay_table: + dc.b 0,4,8,10,12,14,16,18,20,24,32,40,56,96,150,255 + +pre_roll_off_table: + dc.w $400,$200,$180,$140,$100,$C0,$A0,$80,$78,$74,$6E + dc.w $69,$64,$5A,$46,$40,$38,$30,$28,$20,$1F,$1E,$1D + dc.w $1C,$1B,$1A,$19,$18,$17,$16,$15,$14,$13,$12,$11 + dc.w $10,15,14,13,13,12,12,11,11,10,10,9,9,8,8,8,8,7,7 + dc.w 7,7,6,6,6,6,5,5,5,5,4,4,4,4,4,4,4,4,4,4,3,4,4,3,4 + dc.w 4,3,4,3,4,3,4,3,4,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3 + dc.w 2,3,3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,2,2,2,2,2,2,2,1 + dc.w 2,1,2,1,2,1,2,1,1,2,1,1,1,2,1 + +pre_ramp_up_16: + dc.b 0,1,3,6,7,9,10,11,12,13,14,16,19,35,55,143 + +pre_fast_roll_off_16: + dc.w $400,$200,$80,$64,$50,$40,$30,$20,$10,14,12,10,8 + dc.w 4,2,1 + +pre_octave_note_offset_table: + dc.b 1*NOTES_IN_OCTAVE*4,1*NOTES_IN_OCTAVE*4,1*NOTES_IN_OCTAVE*4 + dc.b 2*NOTES_IN_OCTAVE*4,2*NOTES_IN_OCTAVE*4,2*NOTES_IN_OCTAVE*4 + dc.b 3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4 + dc.b 3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4 + dc.b 3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4 + IFNE PRETRACKER_PARANOIA_MODE + dc.b 3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4 + dc.b 3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4 + dc.b 3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4,3*NOTES_IN_OCTAVE*4 + ELSE + dc.b 3*NOTES_IN_OCTAVE*4 + ENDC + even + + ; based on pitch $219 (537), covers up to pitch 0x819 (2073). + ; In practice, I was unable to get higher than $5ff +pre_octave_select_table: + dc.b 1,1,1 + dc.b 2,2,2 + dc.b 3,3,3 + dc.b 3,3,3 + dc.b 3,3,3 + dc.b 3,3,3 + IFNE PRETRACKER_PARANOIA_MODE + dc.b 3,3,3 + dc.b 3,3,3 + ELSE + dc.b 3 + ENDC + even + + IFNE PRETRACKER_DUBIOUS_PITCH_SHIFT_FOR_DELAYED_TRACK + ; -4,-3,-1,1,2,3,4,0 +pre_minus4plus4_table: + dc.b $FC,$FB,$FF,1,2,3,4,0 + ENDC + +pre_ramp_up_down_32: + dc.w 0*32,1*32,2*32,3*32,4*32,5*32,6*32,7*32,8*32,9*32,10*32,11*32,12*32,13*32,14*32,15*32 + dc.w 15*32,14*32,13*32,12*32,11*32,10*32,9*32,8*32,7*32,6*32,5*32,4*32,3*32,2*32,1*32,0*32 + +pre_modulator_ramp_8: + ;dc.w 77,293,539,1079,1337,1877,2431,3031 ; the 1079 value is strange (938 better?) + dc.w $4D,$125,$21B,$437,$539,$755,$96D,$BD7 + +pre_period_table: + dc.w $350,$320,$2F2,$2C8,$2A0,$279,$256,$236,$216,$1F8,$1DC,$1C0 + dc.w $1A8,$190,$179,$164,$151,$13E,$12C,$11B,$10B,$FC,$EE,$E0 + dc.w $D4,$C8,$BD,$B2,$A8,$9F,$96,$8D,$86,$7E,$78,$71 + dc.w $71