1
0
mirror of https://frontier.innolan.net/github/AmigaExamples.git synced 2026-01-13 00:58:30 +00:00

text work in progress

This commit is contained in:
alpine9000
2016-03-26 14:18:51 +11:00
parent c895aad560
commit 8bd7b3e350
17 changed files with 1105 additions and 0 deletions

25
024.simple_text/Makefile Normal file
View File

@ -0,0 +1,25 @@
EXAMPLE_NAME=simple_text
USERSTACK_ADDRESS=7fffc # userstack used by bootblock
BASE_ADDRESS=4000 # if you change this you must also change link.script.x
# note: this must be high enough not to conflict with MFMbufE
BOOTBLOCK_ASM=alpine_bootblock.s
OBJS=out/init.o out/utils.o out/trackloader.o out/image.o out/disk.o out/blit.o out/cpu.o
IMAGES=font.png
IMAGEDATA=$(addprefix out/, $(IMAGES:.png=.bin))
VASM_EXTRA_ARGS=
#SYMBOL_INFO=-M
LINK_COMMANDLINE=vlink -T link.script.x -brawbin1 $< $(OBJS) $(SYMBOL_INFO) -o out/main.bin
include ../shared/base.mk
out/%.bin: ../assets/%.png
$(IMAGECON) --input $< $(IMAGECON_ARGS) --output-bitplanes --output-palette-asm --output-palette --output out/$* --colors=16 --use-palette palette.pal --output-mask
out/main.o: $(IMAGEDATA) constants.i Makefile link.script.x palette.pal
out/init.o: constants.i Makefile

19
024.simple_text/README.md Normal file
View File

@ -0,0 +1,19 @@
photo slideshow
===============
The main theme of this demo is trackloading data whilst the application is running.
We cram a DD floppy full of image and music data, then load and display each image in turn whilst playing a P61 module.
There are quite a few new things in here:
* We use a [modified bootloader](alpine_bootloader.s) that reads the size of the main program from the disk before trackloading it.
* Photon's trackloader is also now copied into the main program so it can be used to load subsequent data.
* We use multiple sections and a [linker script](link.script.x) to help with organising data on the ADF image. The linker script is not technically required, however I wanted to see what I could do with vlink and linker scripts.
* We switched to the [doynamite68k](https://github.com/AxisOxy/Planet-Rocklobster/tree/master/tools/doynamite68k) compressor/decompressor. The compressed file are larger than those generated by Shinkler, however the decompressor is a lot faster.
* P61 is configured to use CIA mode.
try it
------
* [Download disk image](bin/slideshow.adf?raw=true)
* <a href="http://alpine9000.github.io/ScriptedAmigaEmulator/#amiga_examples/slideshow.adf" target="_blank">Run in SAE</a>

View File

@ -0,0 +1,352 @@
*** hardware trackloader bootblock
*** original BootLoader.S by Photon ;NOTE: PC-relative code is PREFERRED.
*** see http://coppershade.org/asmskool/SOURCES/Photon-snippets/DDE5-BootLoader.S
*** this version hacked by alpine9000
include "../include/registers.i"
LoaderVars equ $100 ;Useful variables, see CPUinfo:
Loader equ $120 ;start of load script
MyUserStack equ USERSTACK_ADDRESS ;SSP is at a safe place, but set user
;stack.
MFMsync equ $4489 ;AmigaDOS standard sync marker.
MFMlen equ 12980 ;Legacy trackdata read length in bytes
ShortWt:MACRO ;CPU-independent nop;nop replacement
tst.w (a6)
ENDM
*** Boot Block starts here ***
Boot: dc.b 'DOS',0
dc.l 0,880
BootCode: ;gathers some data, turns off OS, copies itself to $100
*--- Fetch system info ---*
move.l 4.w,a6 ;execbase (will soon be destroyed)
move.l 294(a6),d4 ;CPUinfo in lowest byte for your use.
sub.l a4,a4 ;VBR will always be 0 when booting
;from floppy. No GetVBR needed.
*--- Fastmem available? ---*
if 1
move.l #$20004,d1 ;fast+largest
else
move.l #$20002,d1 ;chip+largest
endif
jsr -216(a6) ;AvailMem()
move.l d0,d5
sub.l #2048,d5 ;leave room for stacks to grow
moveq #4,d1
jsr -198(a6) ;AllocMem()
and.l #-8,d0
move.l d0,a5 ;Start Address
*--- OS off ---* ;you're nice'n all, but now you die.
lea $dff002,a6 ;Loader uses this custom base addr
tst.w (a6) ;wait out blitter
.wblit: btst #6,(a6)
bne.s .wblit
move.l #$7fff7fff,d1
move.l d1,$9a-2(a6) ;disable interrupts & req
move.w d1,$9c-2(a6) ;play it again Sam
sub.w #$20,d1 ;don't affect Sprite DMA until Vblank
move.w d1,$96-2(a6) ;disable DMA
lea MyUserStack,a7 ;some safe place compatible with
;platform requirements
*--- Copy rest of code/data to fixed address ---*
lea CopyStart(PC),a0
lea (LoaderVars).w,a1
moveq #(BootE-CopyStart)/8,d2
.copyl: move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
dbf d2,.copyl
JMP (Loader).w ;Info from Exec passed in 4 registers
******************** $100.w ********************
CopyStart:
CPUinfo: dc.l 0 ;$100
FastMemSize: dc.l 0 ;$104
SysVBR: dc.l 0 ;$108
FastMemStart: dc.l 0 ;$10c
MFMcyl: dc.w 0
MFMhead: dc.w 0
MFMdrv: dc.w 0
MFMchk: dc.l 0
dc.w 0 ;padding to $120
dc.w 0 ;
dc.w 0 ;
LoadScript: ;At $120, sysinfo in 4 regs, a6=$dff002
lea CPUinfo(PC),a3 ;Use this for PC-rel in a pinch.
movem.l d4/d5/a4/a5,(a3)
bsr.s WaitEOF
lea NullCop(PC),a0
move.l a0,$80-2(a6) ;blank copper
move.w #$87d0,$96-2(a6) ;enable DMA (sprites enabled when used)
*--- load first part ---*
lea BASE_ADDRESS,a0 ; main entry point
if 1
moveq #2,d0 ;from sector 2
move.w #-1,d1 ;num sectors, - ==Step0
jsr LoadMFMB
move.l 4(a0),d1
add.l #512,d1
lsr.l #6,d1
lsr.l #3,d1
moveq #2,d0 ;from sector 2
jsr LoadMFMB
lea $dff000,a6 ;restore plain custombase addr for demo
move.l (a0),a0
jmp (a0) ; -> main entry point
else
-moveq #2,d0 ;from sector 2
move.w #-((mainEnd-mainStart)/512),d1;num sectors, - ==Step0
jsr LoadMFMB
jmp (a0) ; -> main entry point
endif
*** MFMLoader.S by Photon *** ;requires a6=$dff002
WaitEOF:
btst #0,5-2(a6)
beq.s WaitEOF
.w1: cmp.b #$37,6-2(a6)
bne.s .w1
.w2: cmp.b #$37,6-2(a6) ;wait for last PAL line, $138
beq.s .w2
rts
LoadMFMB: ;loadsectors.a0=dst,d0=startsec.W,d1=nrsecs.W(-=Step0)
MOVEM.L D0-D7/A0-A6,-(SP)
lea $bfd100,a4
bsr MotorOn
tst.w d1 ;if neg length,then Step0 first
bpl.s .NoSt0
neg.w d1
.St0: btst #4,$f01(a4) ;head on cyl 0?
beq.s .Rdy0
bsr.s StepOut
bra.s .St0
.Rdy0: lea MFMcyl(PC),a1
clr.w (a1)
.NoSt0: and.l #$ffff,d0
divu #22,d0 ;startcyl
sub.w MFMcyl(PC),d0 ;delta-step
beq.s .StRdy
bmi.s .StOut
subq.w #1,d0
.StIn: bsr.s StepIn
dbf d0,.StIn
bra.s .StRdy
not.w d0 ;=neg+sub#1
.StOut: bsr.s StepOut
dbf d0,.StIn
.StRdy: swap d0 ;startsec within cyl
cmp.w #11,d0
blt.s .Head0
sub.w #11,d0
bra.s .Head1
.Head0: bset #2,(a4)
lea MFMhead(PC),a1
clr.w (a1)
bsr LoadTrak ;read track+decode
beq.s .End
.Head1: bclr #2,(a4) ;Head 1
lea MFMhead(PC),a1
move.w #1,(a1)
bsr LoadTrak ;read track+decode
beq.s .End
bsr.s StepIn ;1 cyl forward
bra.s .Head0
.End: bsr.s MotorOff
MOVEM.L (SP)+,D0-D7/A0-A6
RTS
StepOut:
bset #1,(a4)
lea MFMcyl(PC),a1
subq.w #1,(a1)
ShortWt
bclr #0,(a4)
ShortWt
bset #0,(a4)
bsr.s StepWt
RTS
StepIn:
bclr #1,(a4)
lea MFMcyl(PC),a1
addq.w #1,(a1)
ShortWt
bclr #0,(a4)
ShortWt
bset #0,(a4)
bsr.s StepWt
RTS
StepWt:
moveq #67,d6 ;wait >3 ms
LeaveLine:
.loop1: move.b 6-2(a6),d7
.loop2: cmp.b 6-2(a6),d7
beq.s .loop2
dbf d6,.loop1
RTS
MotorOn:
move.w MFMdrv(PC),d7
addq.w #3,d7
or.b #$78,(a4)
bset d7,(a4)
ShortWt
bclr #7,(a4) ;turns motor on
ShortWt
bclr d7,(a4)
ShortWt
.DiskR: btst #5,$f01(a4) ;wait until motor running
bne.s .DiskR
RTS
MotorOff:
move.w MFMdrv(PC),d7
addq.w #3,d7
bset d7,(a4)
ShortWt
bset #7,(a4)
ShortWt
bclr d7,(a4)
RTS
LoadTrak: ;loadtrack+decode.a0=dst,d0=secoffs,d1=secsleft
MOVE.W D0,-(SP)
MOVE.W D1,-(SP)
;; lea (MFMbuf).w,a1
lea (MFMbuf),a1
move.w #2,$9c-2(a6) ;Clr Req
move.l a1,$20-2(a6)
move.w #$8210,$96-2(a6) ;DskEna
move.w #MFMsync,$7e-2(a6)
move.w #$9500,$9e-2(a6)
move.w #$4000,$24-2(a6)
move.w #$8000+MFMlen/2,$24-2(a6);DskLen(12980)+DmaEn
move.w #$8000+MFMlen/2,$24-2(a6);start reading MFMdata
.Wrdy:
btst #1,$1f-2(a6) ;wait until data read
beq.s .Wrdy
move.w d0,d2
add.w d1,d2 ;highest sec# (d0=lowest)
cmp.w #11,d2
ble.s .NoOvr
moveq #11,d2
.NoOvr: sub.w d0,d2 ;nrsecs
move.l #$55555555,d3 ;and-const
move.w d2,d1
subq.w #1,d1 ;loopctr
.FindS: cmp.w #MFMsync,(a1)+ ;search for a sync word
bne.s .FindS
cmp.b (a1),d3 ;search for 0-nibble
bne.s .FindS
move.l (a1)+,d4 ;decode fmtbyte/trk#,sec#,eow#
move.l (a1)+,d5
and.w d3,d4
and.w d3,d5
add.w d4,d4
or.w d5,d4
lsr.w #8,d4 ;sec#
sub.w d0,d4 ;do we want this sec?
bmi.s .Skip
cmp.w d2,d4
blt.s .DeCode
.Skip: lea 48+1024(a1),a1 ;nope
bra.s .FindS
.DeCode:lea 40(a1),a1 ;found a sec,skip unnecessary data
move.l a1,d6
lea MFMchk(PC),a1
clr.l (a1)
move.l d6,a1
move.l (a1)+,d6 ;decode data chksum.L
move.l (a1)+,d5
and.l d3,d6
and.l d3,d5
add.l d6,d6
or.l d5,d6 ;chksum
lea 512(a1),a2
add.w d4,d4 ;x512
lsl.w #8,d4
lea (a0,d4.w),a3 ;dest addr for this sec
moveq #127,d7
.DClup: move.l (a1)+,d4
move.l (a2)+,d5
and.l d3,d4
and.l d3,d5
eor.l d4,d6 ;EOR with checksum
eor.l d5,d6 ;EOR with checksum
add.l d4,d4
or.l d5,d4
move.l d4,(a3)+
dbf d7,.DClup ;chksum should now be 0 if correct
lea MFMchk(PC),a1
or.l d6,(a1) ;or with track total chksum
move.l a2,a1
dbf d1,.FindS ;decode next sec
MOVE.W (SP)+,D1
MOVE.W (SP)+,D0
move.l MFMchk(PC),d3 ;track total chksum OK?
bne LoadTrak ;no,retry
moveq #0,d0 ;set to start of track
move.w d2,d3
add.w d3,d3
lsl.w #8,d3
add.w d3,a0
sub.w d2,d1 ;sub #secs loaded
RTS
NullCop:
dc.w $1fc,0
dc.w $100,$0200
dc.w $96,$0020 ;ensure sprite DMA is off until needed
dc.w $ffdf,$fffe
dc.l -2
BootE:
*** Boot Block ends here ***
dc.b "BootLoader by Photon/Scoopex"
;pad bootblock to correct size
cnop 0,1024
;MFMbuf is placed here after bootblock end, $3c0.w or so when copied.
MFMbuf equ LoaderVars+(BootE-CopyStart)
MFMbufE equ MFMbuf+MFMlen ;lowest free address. $372e for a full bootblock.
mainStart:
incbin "out/main.bin"
cnop 0,512
mainEnd:
end

99
024.simple_text/blit.s Normal file
View File

@ -0,0 +1,99 @@
include "includes.i"
xdef blitObject64
;; BLTCON? configuration
;; http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node011C.html
;; blitter logic function minterm truth table
;; fill in D column for desired function
;; A(mask) B(bob) C(bg) D(dest)
;; - - - -
;; 0 0 0 0
;; 0 0 1 1
;; 0 1 0 0
;; 0 1 1 1
;; 1 0 0 0
;; 1 0 1 0
;; 1 1 0 1
;; 1 1 1 1
;; read D column from bottom up = 11001010 = $ca
;; this is used in the LF? bits
BLIT_LF_MINTERM equ $ca
BLIT_DEST equ $100
BLIT_SRCC equ $200
BLIT_SRCB equ $400
BLIT_SRCA equ $800
BLIT_ASHIFTSHIFT equ 12 ;Bit index of ASH? bits
BLIT_BOB_WIDTH equ 32 ; Must blit extra word to allow shifting
BLIT_BOB_HEIGHT equ 12
BLIT_BOB_WIDTH_BYTES equ BLIT_BOB_WIDTH/8
BLIT_BOB_WIDTH_WORDS equ BLIT_BOB_WIDTH/16
blitWait:
tst DMACONR(a6) ;for compatibility
.waitblit:
btst #6,DMACONR(a6)
bne.s .waitblit
rts
;; blitobject
;; d0 - xpos
;; d1 - ypos
;; a0 - display
;; a1 - object
;; a2 - mask
blitObject64:
movem.l d0-a6,-(sp)
bsr blitWait
;; d0 = XPOS
;; d1 = YPOS
;; d4 = XPOS_BYTES
move.w d0,d4 ; d4 = XPOS
lsr.w #3,d4 ; d4 = XPOS_BYTES
if 1
sub.w #8,d0
endif
;; this shift will give us the bits to shift (bits 0-3) in bits (12-15) of d0
lsl.w #8,d0 ; BLIT_SOURCE_SHIFT<<BLIT_ASHIFTSHIFT
lsl.w #4,d0 ; BLIT_SOURCE_SHIFT<<BLIT_ASHIFTSHIFT
move.w d0,BLTCON1(A6)
ori.w #BLIT_SRCA|BLIT_SRCB|BLIT_SRCC|BLIT_DEST|BLIT_LF_MINTERM,d0
move.w d0,BLTCON0(A6)
if 1
move.w #$00FF,BLTAFWM(a6) ; no mask for first word
move.w #$0000,BLTALWM(a6) ; mask out last word
else
move.w #$ff00,BLTAFWM(a6) ; no mask for first word
move.w #$0000,BLTALWM(a6) ; mask out last word
endif
move.w #SCREEN_WIDTH_BYTES-BLIT_BOB_WIDTH_BYTES,BLTAMOD(a6) ;A modulo
move.w #SCREEN_WIDTH_BYTES-BLIT_BOB_WIDTH_BYTES,BLTBMOD(a6) ;B modulo
move.w #SCREEN_WIDTH_BYTES-BLIT_BOB_WIDTH_BYTES,BLTCMOD(a6) ;C modulo
move.w #SCREEN_WIDTH_BYTES-BLIT_BOB_WIDTH_BYTES,BLTDMOD(a6) ;D modulo
move.l a2,BLTAPTH(a6) ; mask bitplane
move.l a1,BLTBPTH(a6) ; bob bitplane
move.w #SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH,d3 ; d3 = SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH
mulu.w d1,d3 ; d3 = YPOS*SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH
move.l a0,d0 ; d0 = #bitplanes
add.w d4,d0 ; d0 = #bitplanes+XPOS_BYTES
add.w d3,d0 ; d0 = #bitplanes+XPOS_BYTES+(YPOS*SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH)
move.l d0,BLTCPTH(a6) ;background top left corner
move.l d0,BLTDPTH(a6) ;destination top left corner
move.w #(BLIT_BOB_HEIGHT*SCREEN_BIT_DEPTH)<<6|(BLIT_BOB_WIDTH_WORDS),BLTSIZE(a6) ;rectangle size, starts blit
movem.l (sp)+,d0-a6
rts

View File

@ -0,0 +1,10 @@
SCREEN_WIDTH equ 320
SCREEN_HEIGHT equ 256
SCREEN_WIDTH_BYTES equ (SCREEN_WIDTH/8)
SCREEN_BIT_DEPTH equ 4
SCREEN_RES equ 8 ; 8=lo resolution, 4=hi resolution
RASTER_X_START equ $81 ; hard coded coordinates from hardware manual
RASTER_Y_START equ $2c
RASTER_X_STOP equ RASTER_X_START+SCREEN_WIDTH
RASTER_Y_STOP equ RASTER_Y_START+256
IMAGESIZE equ SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH*SCREEN_HEIGHT

28
024.simple_text/cpu.s Normal file
View File

@ -0,0 +1,28 @@
include "includes.i"
xdef CpuFillColor
CpuFillColor:
;; d0 - color index
;; a0 - bitplane pointer
movem.l d1-d4/a0,-(sp)
move.w #(SCREEN_HEIGHT)-1,d2
.fillLine
move.b #0,d1 ; bitplane #
.fillBitplane:
move.w #(SCREEN_WIDTH_BYTES/4)-1,d3 ; long word moves, so / 4
btst d1,d0 ; is the color's bit set in this plane?
beq .zero
move.l #$FFFFFFFF,d4 ; yes ? all ones
bra .loop
.zero
move.l #0,d4 ; no ? all zeros
.loop:
move.l d4,(a0)+ ; write the data to the plane's line
dbra d3,.loop
add.b #1,d1
cmp.b #SCREEN_BIT_DEPTH,d1 ; all planes for a single line done ?
bne .fillBitplane ; no ? do the next plane
dbra d2,.fillLine ; yes ? do the next line
movem.l (sp)+,d1-d4/a0
rts

27
024.simple_text/disk.s Normal file
View File

@ -0,0 +1,27 @@
xdef LoadDiskData
LoadDiskData:
;; a0 - destination address
;; a1 - start address
;; d0 - size
movem.l d0-a6,-(sp)
lea $dff002,a6 ; LoadMFMB uses this custom base addr
move.l d0,d1
move.l a1,d0
move.l #startCode,d2
sub.l d2,d0 ; offset from start of this module
lsr.l #6,d0 ; bytes -> sectors
lsr.l #3,d0
add.l #2,d0 ; offset for bootblock
add.l #512,d1
lsr.l #6,d1 ; bytes -> sectors
lsr.l #3,d1
neg.w d1
jsr LoadMFMB ; load the data!
movem.l (sp)+,d0-a6
rts

BIN
024.simple_text/font.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

54
024.simple_text/image.s Normal file
View File

@ -0,0 +1,54 @@
include "includes.i"
xdef DisplayBitplane
LoadImage:
;; d0 - size
;; a1 - start address
;; a2 - InstallColorPalette(X) address
lea bitplanes3,a0
bsr LoadDiskData ; load data from disk
;; move.l nextbitplane,a1 ; decompress into offscreen bitplanesp(1/2)
;; a0 = Input buffer to be decompressed. Must be 16-bit aligned!
;; a1 = Output buffer. Points to the end of the data at exit
jsr Depack
jsr WaitVerticalBlank ; avoid tearing when we show the new image
jsr (a2) ; install new color palette
jsr DisplayBitplane ; display new image
rts
DisplayBitplane:
;; a0 - bitplane address
movem.l d0/a0-a1,-(sp)
moveq.l #0,d0
move.l a0,a1
lea copperListBplPtr,a0
jsr PokeBitplanePointers
movem.l (sp)+,d0/a0-a1
rts
PokeBitplanePointers:
; d0 = frame offset in bytes
; a0 = BPLP copper list address
; a1 = bitplanes pointer
movem.l d0-a6,-(sp)
add.l d0,a1 ; Offset for odd/even frames
moveq #SCREEN_BIT_DEPTH-1,d0
.bitplaneloop:
move.l a1,d1
move.w d1,2(a0)
swap d1
move.w d1,6(a0)
lea SCREEN_WIDTH_BYTES(a1),a1
addq #8,a0
dbra d0,.bitplaneloop
movem.l (sp)+,d0-a6
rts

View File

@ -0,0 +1,7 @@
include "../include/registers.i"
include "../include/vector.i"
include "../include/beambits.i"
include "../include/bplconbits.i"
include "hardware/dmabits.i"
include "hardware/intbits.i"
include "constants.i"

32
024.simple_text/init.s Normal file
View File

@ -0,0 +1,32 @@
include "includes.i"
xdef Init
;; custom chip base globally in a6
Init:
movem.l d0-a6,-(sp)
;; move #$7ff,DMACON(a6) ; disable all dma
;; move #$7fff,INTENA(a6) ; disable all interrupts
;; lea Level3InterruptHandler,a3
;; move.l a3,LVL3_INT_VECTOR
;; set up playfield
move.w #(RASTER_Y_START<<8)|RASTER_X_START,DIWSTRT(a6)
move.w #((RASTER_Y_STOP-256)<<8)|(RASTER_X_STOP-256),DIWSTOP(a6)
move.w #(RASTER_X_START/2-SCREEN_RES),DDFSTRT(a6)
move.w #(RASTER_X_START/2-SCREEN_RES)+(8*((SCREEN_WIDTH/16)-1)),DDFSTOP(a6)
move.w #(SCREEN_BIT_DEPTH<<12)|COLOR_ON,BPLCON0(a6)
move.w #SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH-SCREEN_WIDTH_BYTES,BPL1MOD(a6)
move.w #SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH-SCREEN_WIDTH_BYTES,BPL2MOD(a6)
;; install copper list, then enable dma and selected interrupts
lea copperList,a0
move.l a0,COP1LC(a6)
move.w COPJMP1(a6),d0
move.w #(DMAF_BLITTER|DMAF_SETCLR!DMAF_COPPER!DMAF_RASTER!DMAF_MASTER),DMACON(a6)
;; move.w #(INTF_SETCLR|INTF_VERTB|INTF_INTEN),INTENA(a6)
movem.l (sp)+,d0-a6
rts

View File

@ -0,0 +1,28 @@
MEMORY
{
disk: org = 0x4000, len = 901120-0x4000
ram: org = 0x00000, len = 0x80000
}
SECTIONS
{
load : {
startCode = .;
*(.text)
*(.data)
*(CODE)
*(DATA)
endCode = .;
} > disk
noload ALIGN(512) : {
startData = .;
*(.noload)
endData = .;
} > disk
bss (NOLOAD) : {
. = endCode;
*(.bss)
} > ram;
}

21
024.simple_text/module.s Normal file
View File

@ -0,0 +1,21 @@
xdef LoadModule
LoadModule:
movem.l d0-a6,-(sp)
lea bitplanes1,a0
lea compressedModule,a1
move.l #endCompressedModule,d0
sub.l #compressedModule,d0
;; a0 - destination address
;; a1 - start address
;; d0 - size
jsr LoadDiskData
;; a0 - input buffer to be decompressed. Must be 16-bit aligned!
;; a1 - output buffer. Points to the end of the data at exit
lea bitplanes1,a0
lea Module,a1
jsr Depack
movem.l (sp)+,d0-a6
rts

View File

@ -0,0 +1,17 @@
000 000 000 000
255 255 255 255
255 000 000 255
000 255 000 255
000 000 255 255
555 555 555 255
255 255 000 255
255 255 000 255
255 255 000 255
255 255 000 255
255 255 000 255
255 255 000 255
255 255 000 255
255 255 000 255
255 255 000 255
255 255 000 255

View File

@ -0,0 +1,139 @@
include "includes.i"
xdef PokeBitplanePointers
xdef copperList
xdef copperListAlternate
xdef bitplanes1
xdef bitplanes2
xdef bitplanes3
xdef Module
xdef copperListBplPtr
xdef copperListAlternateBplPtr
byteMap:
dc.l Entry
dc.l endCode-byteMap
Entry:
lea userstack,a7
lea CUSTOM,a6
move #$7ff,DMACON(a6) ; disable all dma
move #$7fff,INTENA(a6) ; disable all interrupts
jsr InstallPalette
lea Level3InterruptHandler,a3
move.l a3,LVL3_INT_VECTOR
move.w #(INTF_SETCLR|INTF_VERTB|INTF_INTEN),INTENA(a6)
lea bitplanes1,a0
move.l #4,d0 ;color
jsr CpuFillColor
jsr DisplayBitplane ; select it
if 0
lea bitplanes2,a0
move.l #3,d0 ;color
jsr CpuFillColor
endif
jsr Init ; enable the playfield
.mainLoop:
jsr WaitVerticalBlank
jsr WaitVerticalBlank
jsr WaitVerticalBlank
jsr WaitVerticalBlank
jsr WaitVerticalBlank
;; blitobject64
;; d0 - xpos
;; d1 - ypos
;; a0 - display
;; a1 - object
;; a2 - mask
;; add.l #1,xpos
move.l #4,xpos
move.l xpos,d0
move.l #50,d1
lea bitplanes1,a0
if 1
sub.l #2,a0
endif
lea font,a1
lea fontMask,a2
jsr blitObject64
bra .mainLoop
xpos:
dc.l 0
Level3InterruptHandler:
movem.l d0-a6,-(sp)
lea CUSTOM,a6
.checkVerticalBlank:
move.w INTREQR(a6),d0
and.w #INTF_VERTB,d0
beq.s .checkCopper
.verticalBlank:
move.w #INTF_VERTB,INTREQ(a6) ; clear interrupt bit
.checkCopper:
move.w INTREQR(a6),d0
and.w #INTF_COPER,d0
beq.s .interruptComplete
.copperInterrupt:
move.w #INTF_COPER,INTREQ(a6) ; clear interrupt bit
.interruptComplete:
movem.l (sp)+,d0-a6
rte
copperList:
copperListBplPtr:
dc.w BPL1PTL,0
dc.w BPL1PTH,0
dc.w BPL2PTL,0
dc.w BPL2PTH,0
dc.w BPL3PTL,0
dc.w BPL3PTH,0
dc.w BPL4PTL,0
dc.w BPL4PTH,0
dc.w BPL5PTL,0
dc.w BPL5PTH,0
dc.w BPL6PTL,0
dc.w BPL6PTH,0
dc.w $106,$c00 ;AGA sprites, palette and dual playfield reset
dc.w $1FC,0 ;AGA sprites and burst reset
dc.l $fffffffe
dc.l $fffffffe
InstallPalette:
include "out/font-palette.s"
rts
font:
incbin "out/font.bin"
fontMask:
incbin "out/font-mask.bin"
section .bss
bitplanes1:
ds.b IMAGESIZE+(512)
bitplanes2:
ds.b IMAGESIZE+(512*2)
bitplanes3:
ds.b IMAGESIZE+(512*3)
startUserstack:
ds.b $1000 ; size of stack
userstack:

View File

@ -0,0 +1,203 @@
*** MFMLoader.S by Photon *** ;requires a6=$dff002
xdef LoadMFMB
MFMsync equ $4489 ;AmigaDOS standard sync marker.
MFMlen equ 12980 ;Legacy trackdata read length in bytes
ShortWt:MACRO ;CPU-independent nop;nop replacement
tst.w (a6)
ENDM
MFMcyl: dc.w 0
MFMhead: dc.w 0
MFMdrv: dc.w 0
MFMchk: dc.l 0
LoadMFMB: ;loadsectors.a0=dst,d0=startsec.W,d1=nrsecs.W(-=Step0)
MOVEM.L D0-D7/A0-A6,-(SP)
lea $bfd100,a4
bsr MotorOn
tst.w d1 ;if neg length,then Step0 first
bpl.s .NoSt0
neg.w d1
.St0: btst #4,$f01(a4) ;head on cyl 0?
beq.s .Rdy0
bsr.s StepOut
bra.s .St0
.Rdy0: lea MFMcyl(PC),a1
clr.w (a1)
.NoSt0: and.l #$ffff,d0
divu #22,d0 ;startcyl
sub.w MFMcyl(PC),d0 ;delta-step
beq.s .StRdy
bmi.s .StOut
subq.w #1,d0
.StIn: bsr.s StepIn
dbf d0,.StIn
bra.s .StRdy
not.w d0 ;=neg+sub#1
.StOut: bsr.s StepOut
dbf d0,.StIn
.StRdy: swap d0 ;startsec within cyl
cmp.w #11,d0
blt.s .Head0
sub.w #11,d0
bra.s .Head1
.Head0: bset #2,(a4)
lea MFMhead(PC),a1
clr.w (a1)
bsr LoadTrak ;read track+decode
beq.s .End
.Head1: bclr #2,(a4) ;Head 1
lea MFMhead(PC),a1
move.w #1,(a1)
bsr LoadTrak ;read track+decode
beq.s .End
bsr.s StepIn ;1 cyl forward
bra.s .Head0
.End: bsr.s MotorOff
MOVEM.L (SP)+,D0-D7/A0-A6
RTS
StepOut:
bset #1,(a4)
lea MFMcyl(PC),a1
subq.w #1,(a1)
ShortWt
bclr #0,(a4)
ShortWt
bset #0,(a4)
bsr.s StepWt
RTS
StepIn:
bclr #1,(a4)
lea MFMcyl(PC),a1
addq.w #1,(a1)
ShortWt
bclr #0,(a4)
ShortWt
bset #0,(a4)
bsr.s StepWt
RTS
StepWt:
moveq #67,d6 ;wait >3 ms
LeaveLine:
.loop1: move.b 6-2(a6),d7
.loop2: cmp.b 6-2(a6),d7
beq.s .loop2
dbf d6,.loop1
RTS
MotorOn:
move.w MFMdrv(PC),d7
addq.w #3,d7
or.b #$78,(a4)
bset d7,(a4)
ShortWt
bclr #7,(a4) ;turns motor on
ShortWt
bclr d7,(a4)
ShortWt
.DiskR: btst #5,$f01(a4) ;wait until motor running
bne.s .DiskR
RTS
MotorOff:
move.w MFMdrv(PC),d7
addq.w #3,d7
bset d7,(a4)
ShortWt
bset #7,(a4)
ShortWt
bclr d7,(a4)
RTS
LoadTrak: ;loadtrack+decode.a0=dst,d0=secoffs,d1=secsleft
MOVE.W D0,-(SP)
MOVE.W D1,-(SP)
lea MFMbuf,a1
move.w #2,$9c-2(a6) ;Clr Req
move.l a1,$20-2(a6)
move.w #$8210,$96-2(a6) ;DskEna
move.w #MFMsync,$7e-2(a6)
move.w #$9500,$9e-2(a6)
move.w #$4000,$24-2(a6)
move.w #$8000+MFMlen/2,$24-2(a6);DskLen(12980)+DmaEn
move.w #$8000+MFMlen/2,$24-2(a6);start reading MFMdata
.Wrdy:
btst #1,$1f-2(a6) ;wait until data read
beq.s .Wrdy
move.w d0,d2
add.w d1,d2 ;highest sec# (d0=lowest)
cmp.w #11,d2
ble.s .NoOvr
moveq #11,d2
.NoOvr: sub.w d0,d2 ;nrsecs
move.l #$55555555,d3 ;and-const
move.w d2,d1
subq.w #1,d1 ;loopctr
.FindS: cmp.w #MFMsync,(a1)+ ;search for a sync word
bne.s .FindS
cmp.b (a1),d3 ;search for 0-nibble
bne.s .FindS
move.l (a1)+,d4 ;decode fmtbyte/trk#,sec#,eow#
move.l (a1)+,d5
and.w d3,d4
and.w d3,d5
add.w d4,d4
or.w d5,d4
lsr.w #8,d4 ;sec#
sub.w d0,d4 ;do we want this sec?
bmi.s .Skip
cmp.w d2,d4
blt.s .DeCode
.Skip: lea 48+1024(a1),a1 ;nope
bra.s .FindS
.DeCode:lea 40(a1),a1 ;found a sec,skip unnecessary data
move.l a1,d6
lea MFMchk(PC),a1
clr.l (a1)
move.l d6,a1
move.l (a1)+,d6 ;decode data chksum.L
move.l (a1)+,d5
and.l d3,d6
and.l d3,d5
add.l d6,d6
or.l d5,d6 ;chksum
lea 512(a1),a2
add.w d4,d4 ;x512
lsl.w #8,d4
lea (a0,d4.w),a3 ;dest addr for this sec
moveq #127,d7
.DClup: move.l (a1)+,d4
move.l (a2)+,d5
and.l d3,d4
and.l d3,d5
eor.l d4,d6 ;EOR with checksum
eor.l d5,d6 ;EOR with checksum
add.l d4,d4
or.l d5,d4
move.l d4,(a3)+
dbf d7,.DClup ;chksum should now be 0 if correct
lea MFMchk(PC),a1
or.l d6,(a1) ;or with track total chksum
move.l a2,a1
dbf d1,.FindS ;decode next sec
MOVE.W (SP)+,D1
MOVE.W (SP)+,D0
move.l MFMchk(PC),d3 ;track total chksum OK?
bne LoadTrak ;no,retry
moveq #0,d0 ;set to start of track
move.w d2,d3
add.w d3,d3
lsl.w #8,d3
add.w d3,a0
sub.w d2,d1 ;sub #secs loaded
RTS
;MFMbuf is placed here after bootblock end, $3c0.w or so when copied.
MFMbuf:
dcb.b MFMlen

44
024.simple_text/utils.s Normal file
View File

@ -0,0 +1,44 @@
xdef WaitVerticalBlank
xdef WaitRaster
xdef Depack
WaitVerticalBlank:
movem.l d0,-(sp)
.loop: move.l $dff004,d0
and.l #$1ff00,d0
cmp.l #303<<8,d0 ; wait for the scan line
bne.b .loop
.loop2 move.l $dff004,d0
and.l #$1ff00,d0
cmp.l #303<<8,d0 ; wait for the scal line to pass (A4000 is fast!)
beq.b .loop2
movem.l (sp)+,d0
rts
WaitRaster: ;wait for rasterline d0.w. Modifies d0-d2/a0.
movem.l d0-a6,-(sp)
move.l #$1ff00,d2
lsl.l #8,d0
and.l d2,d0
lea $dff004,a0
.wr: move.l (a0),d1
and.l d2,d1
cmp.l d1,d0
bne.s .wr
movem.l (sp)+,d0-a6
rts
Depack:
;a0 = input buffer to be decompressed. Must be 16-bit aligned!
;a1 = output buffer. Points to the end of the data at exit
movem.l d0-a6,-(sp)
bsr doynaxdepack ; decompress data
movem.l (sp)+,d0-a6
rts
;; this is one FAST decompression routine!
include "../tools/external/doynamite68k/depacker_doynax.asm"