GAMEX
game launcher code source with comments
* Castle Master Gamex/normal
play launcher
* Compatible on all ST(E) , Falcon ....
*
*
* running from hard drive
* Game exit to Desktop, pos saving
* 2MB RAM needed... 1MB vers. too much complications would be...
* but with 1MB can play normally, without Gamex
* Created by P. Putnik, April-July 2009 .
* This is likely final version - with all RAM tests, MSTE, Falcon
settings
* Launcher stage 1:
testing low RAM occupation, physical RAM size
* by ST(E) - abort if not enough RAM, set gxf (gamex flag)
* reserving TOP RAM - lovering (or increasing if is already
lowered) memtop, phystop.
* Gamex Values for this game:
GameScrB equ
$F8000 *For games working with 1M
AltRamPos equ $100000
*
Here will copy low RAM by game exit . At offset 8 .
* Usually same as New Phystop
MainInb equ
$1FFF40 * All relevant addresses for header build and
continue from RAM here
* Pointer to MainInb is always at Phystop+4
SwapLen equ
$DFCF8 * in fact save len
GameRest equ $FFD20 * Place
for game restoring code, stage 2, which swaps RAM
* always save as much as this launcher
reaches
* together with both SP in moment of launching game !!!!
* so, set them to be in workspace of ...
FreeMem equ
$1FFD20 *For 1M games, 2MB total RAM
SysStor equ
$1FFF80 *Place for storing TOS system - 128
bytes
begin *Beginning of program
* Low RAM usage check and exit if too much is used...
* not really needed when no Gamex, but is good to inform user
* that better run games without too much crap in low RAM !
lea hwpal(pc),a1
cmp.l
#FreeMem-DeskCopy-48,a1 *Place available in high RAM to store TOS
* In fact, by RAM over 2MB DeskCopy may be placed over 2MB .... later...
bcs.s lowRamOK
lea
lowRamTM(pc),a0 *Message
toPMex bsr pmess
move.w #1,-(sp) *Give
chance for user to read it ...
trap #1
addq.l #2,sp
clr.w -(sp)
trap #1 *Exit
lowRamOK
NewPhyst equ $100000 *For 1M
games - usually same as AltRamPos, but may be lower
* First test HW, if only 512KB phys. then skip whole Gamex stuff
pea
hwdet(pc)
*Call supervisor code for HW test
move.w #38,-(sp)
trap #14
addq.l #6,sp
lea
machin(pc),a1 *TOS vers. major
cmp.b #3,(a1) *TT TOS vers.
beq.s low_sp
cmp.b #4,(a1) *Falcon
TOS
vers.
beq.s low_sp
* Check Physical RAM size
cmp.b #1,7(a1) * Is only
512K ? RAM size in 512KB steps, byte var.
bne.s che1m
lea
RAMne(pc),a0
* Message and abort if only 512K
bra.s toPMex
che1m
cmp.b #2,7(a1) * Is only 1M
?
sne gxf * Set Gamex flag if
over 1MB ( = min 2MB )
low_sp
move.l 4(sp),a2
*basepage adr.
lea $F7FE0,sp
*Must move stack below 1M
clr.l (sp)
move.l a2,4(sp)
* Set basepage pointer in new stack
* Following will correct memtop, Phystop, this allocation variables by
need :
get_bp
move.b
#2,machin+2 * 'Set' TOS RAM size
move.l
a2,basep
move.l 4(a2),d2
*memtop
move.l d2,memt
move.l #NewPhyst,d1
sub.l
#$8000,d1 *This
is new memtop
move.l
d1,4(a2) * Correct in basepage
* Conditional settings in subrutine following :
pea lowmsuv(pc)
move.w #38,-(sp)
trap #14
addq.l #6,sp
* Now TOP RAM is reserved, TOS sees only 1MB of RAM !
* Launcher stage 2: set
screen, storing stack pointers, MFP, screen
stage2
* Get current screen resolution:
move.w #4,-(sp)
trap #14
addq.l #2,sp
* Falcon patch:
cmp.w #3,d0 *Allow
only 0-2 !
bcs.s store_res
clr.w d0
store_res move.w d0,DeskRes
dc.w
$A00A * Hide mouse
clr.w -(sp) *set low
res
pea GameScrB
pea GameScrB
move.w #5,-(sp)
trap #14
lea 12(sp),sp
*We need supervisor mode from now :
clr.l -(sp)
move.w #32,-(sp)
trap #1
addq.l #6,sp
move.l d0,uspstor
tst.b gxf
beq show_hw * Skip
gamex part if only 1M
stage22
* Preparing some IKBD storage:
* Will be executed by restoring TOS, when exit game
move.w #34,-(sp)
*Kbdvbase
trap #14
addq.l
#2,sp
move.l d0,a1
lea
32(a1),a1 * IKBD system vector
move.l
a1,ikbdsysv * Write in TOS restoring code
move.l (a1),orgikbds
*
SysStor struct :
* relative pos, what
* 0 USP
* 4 Desktop screen
resolution at prg start !
* 6 SSP
* 10 Palette, 32 bytes
* 42 MFP state, 24 bytes
* 66 ?
* 66 bytes used so far (128 avail)
mfpof equ 42
lea SysStor+10,a6
*palette store pos
* Save desktop palette:
lea $FFFF8240.w,a1
moveq #15,d1
.palc move.w (a1)+,(a6)+
dbf d1,.palc
* Saving MFP state.....
lea $FFFFFA01.w,a1
moveq #23,d2 *24
registers, up to $FFFA2F
.mfpsl move.b (a1),(a6)+
addq.l #2,a1
dbf d2,.mfpsl
*Timer B and C needs accurate reading:
* Other 2 is off in TOS....
*So we read them some time and take
*Max value:
* To speed it up we can test both in same time !
lea $FFFFFA21.w,a1
lea $FFFFFA23.w,a2
move.w #3777,d7
*Determines time for read
clr.b d2
clr.b d4
retimbl move.b (a1),d1
cmp.b d1,d2
bcc.s renotbb
rebiggerb move.b d1,d2
renotbb move.b (a2),d3
cmp.b d3,d4
bcc.s renotbc
rebiggerc move.b d3,d4
renotbc dbf d7,retimbl
move.b d2,-8(a6)
* Timer B Data reg
move.b d4,-7(a6)
* Timer C Data reg.
* TOS values are normally: Timer B: $41 (PAL mode), Timer
C: $C0 !
* Launcher stage 3:
storing TOS, desktop, this prg active
part in * Upper RAM for later restore
* Best is that we do HW show and pic show at this point !!
show_hw
bsr clearkb
move.l
#GameScrB,screnb *screen pos. for pic show
pea hwpal(pc) *
Palette with blue text
move.w #6,-(sp)
trap #14
addq.l #6,sp
move.w #37,-(sp)
trap #14
addq.l #2,sp
bsr machipr *HW
detected printing
lea langs(pc),a0
* This is game specific selection, for Castle Master only !
bsr pmess
* Define some pause, to see it:
move.w #1177,d7
dell1 move.w #37,-(sp)
trap #14
addq.l #2,sp
* Allow abort with keypress:
pea $600ff
trap #1
addq.l #4,sp
tst.b d0
beq.s cycl
cmp.b #"M",d0
beq megastes * Optional MSTE
or Falcon settings
cmp.b #"m",d0
beq megastes
andi.b #$DF,d0 * Game
specific
cmp.b #$44,d0 *
Allows entering only D, E or F
blt.s cycl
cmp.b #$46,d0
bgt.s cycl
move.b d0,$200.w
bra.s toPicsh
cycl dbf d7,dell1
toPicsh
lea infstr(pc),a0 *
Again game specific
bsr pmess
move.w #1,-(a7)
trap #1
addq.l #8,a7
ori.b #$20,d0
move.b d0,$300.w
* Trainer or not above
cmp.b #4,machin
bne.s steph *Skip pic
show on Falc.
* Falcon Pic show:
bsr falcpic
bra.s loadg
steph
bsr photoc *Call Photochrome pic
show rut., on (M)ST(E)
loadg
* Game specific - need Mshrink before pexec game executables
pea hwpal-begin+266
pea begin-256(pc)
pea $4A0000
*Mshrink
trap #1
lea $C(a7),a7
*now set stack pointers in area what will be
saved up
* and this is imortant for following pexec too here !
lea hwpal(pc),sp
lea -200(sp),a1
move.l a1,usp
tst.b gxf
beq lau_2
lea SysStor,a6
move.l
a1,(a6)+ *Store USP
move.w DeskRes(pc),(a6)+
move.l sp,(a6)
*SSP to SysStor ....
* Header build support #2 :
* Fill MainInb :
lea MainInb,a2
lea 64(a2),a1
move.l #SwapLen,(a2)+
move.l
#FreeMem,(a2)+
move.l #SysStor,(a2)+
move.l #GameRest,(a2)+
* move.l #GameStat,(a2)+
move.l #depak3,(a2)+
* move.l
#GameStoPl+backingam-gamex,(a2)+
move.l #backingam,(a2)+
move.w #$C3C2,(a2)+
*Keys
clr_maininb clr.w (a2)+
cmp.l a2,a1
bne.s clr_maininb
*Clear rest for future good
* Needs Falcon Cache setting store too
lea MainInb+38,a2
move.w falccach(pc),(a2)
* Saving area from adr 8 to hwpal in high RAM
DeskCopy equ $1A0108
* Game specific ...
* what must be enough for TOS 2.06 with hard ddriver, buffers
lea 8.w,a5 * Always
at adr. 8
lea DeskCopy,a6 *
lea hwpal(pc),a1
move.l a1,d0
divu
#48,d0 *get loop count
move.w
d0,swapln+2 *Set same len for TOS restore *swap part
.cod movem.l
(a5)+,d1-d7/a0-a4 *48 bytes at once
movem.l
d1-d7/a0-a4,(a6)
lea 48(a6),a6
dbf d0,.cod
* Little overshot, no problems...
* Stage 4:
preparing setting Exit to Desktop in stored
mem. :
* We need only regular exit TOS call at certain point...
* Copy code in free area at top top
*FreeMem equ
$1FFD20 *For 1M games, 2MB total RAM
lea GamexCtrl(pc),a1
lea FreeMem,a2
move.w
#127,d2 *There is 768 bytes place !
* But top is reserved for storing state, palette etc....
* so copying only 512 bytes ....
.cou move.l (a1)+,(a2)+
dbf d2,.cou
* Now load game
* Part 1 first :
lau_2
pea 0.w
pea zer(pc)
pea exe1(pc) * Castle1
run
pea $4B0000
trap #1
lea $10(a7),a7
pea 0.w
pea zer(pc)
pea exe2(pc) * Castle2
pea $4B0003 *Load only
trap #1
lea $10(a7),a7
* Now depack this special FIC.... CTE extension used
* CTE means Compressed TOS Executable
* CTE build: at begin is regular TOS header. Code len
is len of packed
* data. Must be terminated with long 0 at even position. Data len
is always 0
* BSS len is same as in unpacked TOS exec
* Following rutine will correct Code and Data len in basepage after
depack :
* Packed data is C3 FIC without header !
* Packed Code is loaded at BP + 256
* So, move up, and then depack to same place...
move.l d0,-(sp)
move.l d0,a1
lea 256(a1),a2
move.l a2,-(sp) * Save code begin
lea $90000,a3 *may be too low on
Falc
tst.b gxf
beq.s copa3
lea $110000,a3
copa3 move.l a3,a1
move.w #26672,d2 * ~ 213379
mou1 move.l (a2)+,(a3)+
move.l (a2)+,(a3)+
dbf d2,mou1
* There is no FIC header ! Of course ....
move.l (sp),a4
lea -28(a4),a4 * Depacking with TOS exec
header !
bsr depak3
move.l (sp)+,a1 *Code begin
* Now reloc :
move.l a1,a0
lea -28(a0),a3 *Header
lea -256(a0),a5 *Basepage
move.l a1,d0
add.l 2(a3),a0
*Code len for this prg
*No data here
* add.l 6(a3),a0
*Data len for this prg
move.l a0,a2 * reloc table begin
tst.l (a0)
beq.s corrbp *
add.l (a0)+,a1
clr.l d1
relol add.l d0,(a1)
bigd
move.b (a0)+,d1
beq.s corrbp
cmp.b #1,d1
bne.s nmd
lea $FE(a1),a1
bra.s bigd
nmd adda.l d1,a1
bra.s relol
corrbp
move.l
2(a3),$C(a5)
*Code len
move.l
6(a3),$14(a5) *Data
len
move.l
$A(a3),$1C(a5)
*BSS len
move.l
8(a5),d2
move.l
$C(a5),d1
add.l d2,d1
move.l
d1,$10(a5)
*Data start adr
move.l
$14(a5),d2
add.l d2,d1
move.l
d1,$18(a5) *BSS
start adr
lea
6600(a0),a0 * May need more by some
xy clr.l (a2)+
*
clear BSS area begin
cmp.l a2,a0
bgt.s xy
move.l (sp)+,d0 *get
BP address back
move.l d0,a5
move.l d0,a3
*
lea gxf(pc),a2
tst.b (a2)
beq.s rungame
* 2 addresses to correct in key test for exit
move.l d0,a2
add.l #$3F5F4-$191E2,a2
move.l a2,gamnoex+2
move.l d0,a2
add.l #$3F66C-$191E2,a2
move.l a2,jubag+2
* Inject game exit activation :
* lea
$DF000,a2 * Game soecific
* lea gamex(pc),a1
* moveq #100,d2
*.gac move.l (a1)+,(a2)+
** dbf d2,.gac
* No need for above as we have this resident in RAM !
* Link to : * To pos $3F666-$191E2
+ d0
add.l #$3F666-$191E2,a3
move.w #$4EF9,(a3)+
* move.l #$DF000,(a3)
move.l #gamex,(a3)
rungame
pea (a5)
pea (a5)
pea (a5)
pea $4B0004 *Start it
trap #1
lea $10(a7),a7
exitu clr.w -(sp)
trap #1
zer dc.b 0,0,0,0
*
gxf
dc.w $0100 *Preset because Falc.
Phys RAM skip at begin
*gemdap dc.l 0
*Game exit code: * Goes to pos: - here stays
gamex cmp.b #$C3,d0
* For F9
beq.s gamex_w
backingam
gamnoex tst.w
$3F5F4 * This 2 address will be corrected according to load pos
jubag jmp
$3F66C
* Above 2 address will be corrected by game load pos.
gamex_w
* Code for game state store when
exit is requested:
*GameStat equ $DF180
*Set for particular game always
*GameStoPl equ
$DF000 *Where to place code for gamestate save
* Here no need for extra RAM locations...
GameSto * The code itself. Must be PC relative !!!
* Presumable we are in supervisor mode....
* For games not running in SV need some switch, workaround...
* will see later....
* 0 USP
* 4 Cur screen resolution -
almost always 0 !
* 6 SSP
* 10 Palette, 32 bytes
* 42 MFP state, 24 bytes
* 66 Screen base
* 70 IKBD joy status, 8 bytes
* 80 SR, 2 bytes
* 84 PSG status, 14 bytes
* 100 IKBD mouse status, 8 bytes
* 108 STE DMA audio if used
* 116 Next thing worth to
store :-)
ikbdof equ 70
ikbdm_of equ 100
srofs equ 80
psgofs equ 84
* Store CPU regs, SR, stack pointers
movem.l d0-d7/a0-a6,-(sp)
* lea GameStat,a6
lea depak3(pc),a6
move.w sr,80(a6)
move.l usp,a1
move.l
a1,(a6)+ *Store USP
move.b $FFFF8260.w,d1
and.w #$3,d1
move.w d1,(a6)+ * Res.
Usually 0
move.l sp,(a6)+ *SSP
* Saving PSG state:
lea $FFFF8800.w,a1
* lea GameStat+psgofs,a2
lea depak3+psgofs,a2
moveq #0,d2
.psgl move.b d2,(a1)
move.b (a1),(a2)+
addq.b #1,d2
cmp.b #14,d2
bne.s .psgl
* Save palette:
lea $FFFF8240.w,a1
moveq #15,d1
.palc move.w (a1)+,(a6)+
dbf d1,.palc
* Saving MFP state.....
* Save MFP registers :
lea $FFFFFA01.w,a1
moveq #23,d2 *24
registers, up to $FFFA2F
.mfpsl move.b (a1),(a6)+
addq.l #2,a1
dbf d2,.mfpsl
*Timer A, C and D need accurate reading:
* we presume that timer B is intact (for now)
*So we read them some time and take
*Max value:
* To speed it up we can test all 3 in same time !
lea $FFFFFA1F.w,a1
*Timer A data
lea $FFFFFA23.w,a2
*Timer C data
lea $FFFFFA25.w,a3
*Timer D data
* Trying with longer test: worked not
move.w #6777,d7
*Determines time for read
clr.b d2
clr.b d4
clr.b d6
gatimbl move.b (a1),d1
cmp.b d1,d2
bcc.s ganotba
move.b d1,d2
ganotba move.b (a2),d3
cmp.b d3,d4
bcc.s ganotbc
move.b d3,d4
ganotbc move.b (a3),d5
cmp.b d5,d6
bcc.s ganotbd
move.b d5,d6
ganotbd
dbf d7,gatimbl
move.b d2,-9(a6)
* Timer A Data reg
move.b d4,-7(a6)
* Timer C Data reg.
move.b d6,-6(a6)
* Timer D Data reg.
* Screen Base:
move.b
$FFFF8201.w,(a6)+ * High byte
move.b
$FFFF8203.w,(a6)+ * Mid byte
* IKBD status will store after setting
TOS workable - in restoring it....
* so, may jump to TOS restore:
* Clear abort flag in game !!!!
* If needed !
jmp FreeMem
* C3 depacker:
depak3 clr.l d0
moveq #6,d4
moveq #$3f,d5 *for
masking bits 5-0
* Bit meaning: 7 - if set it's back referrer , if 0 then bits
* 6-0 give count of literals to copy
* if all bits are 0 it is terminator
* When bit 7 set, bit 6: if 1 then long distance back given by 2
following byte
* bit 6: when 0 then short distance given by following 1
byte
* bits 5-0 count of bytes referred.
* By short refer. 0 means 3, 1 means 4, etc up to 66 .
* By long refer. 0 means 4, 1 means 5, etc up to 67 .
main3 clr.w d0 *prep for dbf
move.b (a1)+,d0
bmi.s back3
beq.s nom3 *end
subq.w #1,d0 *compens dbf
litc move.b (a1)+,(a4)+
dbf d0,litc
bra.s main3
nom3 rts
back3 move.b d0,d2
and.w d5,d2 *d5=$3f
* Test is long or short referrer:
btst d4,d0 *test bit 6
bne.s longr
addq.w #2,d2 *compens
displl move.b (a1)+,d0 * displac
calcadr move.l a4,a2
sub.l d0,a2
baksl move.b (a2)+,(a4)+
dbf d2,baksl
bra.s main3
longr addq.w #3,d2 *compens
move.b (a1)+,d0 * displac
lsl.w #8,d0 *MSB
bra.s displl
* End of C3 depak
* Game files :
exe1 dc.b "CASTLE1.TOS",0
exe2 dc.b "CASTLE2.CTE",0
even
* Rutine for setting new Phystop,
memtop and allocated block's variables
lowmsuv *Supervisor mode needed for set some
sysvars...
move.l $42E.w,d5 *Old Phystop
move.l #NewPhyst,$42E.w
* See is Memtop sysvar $8000 bytes below Phystop :
* By Falcon is usually $7E00 bytes below
move.l $436.w,d3
move.l d5,d4
sub.l d3,d4
move.l #$8000,d3
sub.l d4,d3 *
add diff
sub.l
#NewPhyst,d5 *Get diff.
sub.l d5,$436.w
*Correct Memtop sysvar
sub.l d3,$436.w
* By Falcon if....
* Get os_end :
move.l $4F2.w,a1
move.l
12(a1),a1 *seek until this addr
lea
$800,a2 *from here seek
* Seek basepage value, followed by free RAM for... :
move.l basep(pc),d1
move.l memt(pc),d2
sub.l d1,d2 *free RAM
for
bvseekl cmp.l (a2),d1
bne.s bvseendt
* if found test freeram value matching :
cmp.l 4(a2),d2
beq.s bvgotit
bvseendt addq.l #2,a2
cmp.l a2,a1
bgt.s bvseekl
bvgotit * decrease free RAM value by diff. :
sub.l d5,4(a2)
* Dirty hack, but works !
* By stoopid Falcon it is $200 bytes higher !!!!
sub.l d3,4(a2)
corr_2
* If no RAM for GX skip Signature writing :
tst.b gxf
beq.s fin_lowm
* Header build support #1:
move.l $42E.w,a2
move.l #"PPGX",(a2)+
move.l #MainInb,(a2)
fin_lowm rts
DeskRes dc.w 0
basep dc.l 0
memt dc.l
$F8000 *preset for case...
uspstor dc.l 0
GamexCtrl *Code
for controlling game exit ....
* Must be PC relative !!
RamSwap *This swaps 2 RAM halves
move.w #$2700,sr
* MFP restoring flow:
* disable all MFP interrups
* allow little time that CPU finish
* Clear IE registers
clr.b $FFFFFA07.w
clr.b $FFFFFA09.w
* Clear Pending regs
clr.b $FFFFFA0B.w
clr.b $FFFFFA0D.w
*Clear in Service regs :
clr.b $FFFFFA0F.w
clr.b $FFFFFA11.w
*Some little delay
* Until find not better solution ... ?
move.l #3984,d1
.del subq.l #1,d1
bne.s .del
* Swapping only used Sys area, after it just copy left game area
* to top RAM !!!
* no need for swap, in fact .....
* First copy game up, then TOS down, then rest of game up
* 256KB max at once
ramswp lea 8.w,a5
lea
AltRamPos+8,a6
move.w
#5460,d0 * For 256KB
ramswl
movem.l
(a5)+,d1-d7/a0-a4 *48 bytes at once
movem.l
d1-d7/a0-a4,(a6)
lea 48(a6),a6
*48 bytes in one cycle
tst.b d0
bne.s ramsw_loop
*Little fade/flash :
move.w $FFFF8240.w,d1
addq.w #1,d1
cmp.w #$0FFF,d1
bcs.s .colup
clr.w d1
.colup move.w d1,$FFFF8240.w
ramsw_loop dbf d0,ramswl
* game up to $3FFF8 copied
* Copy saved TOS RAM back down
lea 8.w,a6
lea DeskCopy,a5
swapln move.w #0,d0 *
Will be set in stage 3
.cod2 movem.l
(a5)+,d1-d7/a0-a4 *48 bytes at once
movem.l
d1-d7/a0-a4,(a6)
lea 48(a6),a6
dbf d0,.cod2
* Now only copy remaining of game in high RAM
lea $3FFF8,a5 *src
lea AltRamPos+$3FFF8,a6
*dest
move.w
#13637,d0 *for rest, to $DFCF8 !
by SaveLen !
* Formula: (SwapLen-$3FFF8)/48
.cou movem.l
(a5)+,d1-d7/a0-a4 *48 bytes at once
movem.l
d1-d7/a0-a4,(a6)
lea 48(a6),a6
dbf d0,.cou
* May be little overshot, so set locations min 24 bytes over !
* Now need to restore stack pointers, screen, MFP, PSG ....
* relative pos, what in
SysStor
* 0 USP
* 4 Desktop screen
resolution at prg start !
* 6 SSP
* 10 Palette, 32 bytes
* 42 MFP state....
lea
SysStor,a1
move.l (a1)+,a4
move.l a4,usp
move.w (a1)+,d7
*Resolution
move.l (a1)+,sp
*Set palette pointer Sysvar:
move.l a1,$45A.w
*Colorptr - will set palette in first Vblank
* Here deal with MFP....
lea
$FFFFFA01.w,a1
lea
SysStor+mfpof,a2
moveq #23,d2 *24
registers
mfprl move.b
(a2)+,(a1)
addq.l #2,a1
dbf d2,mfprl
move.w #$2300,sr
*Signal and silencing possible tone
lea forvs(pc),a6
lea $ffff8800.w,a0
moveq #0,d0
sounl move.b d0,(a0)
move.b (a6)+,2(a0)
addq.b #1,d0
cmp.b #14,d0
blt.s sounl
* Flush IKBD ACIA buffer - may be blocked
aciafl btst
#0,$FFFFFC00.w
beq.s aciaempt
tst.b $FFFFFC02.w
bra.s aciafl
aciaempt
move.l #3984,d1
.del subq.l #1,d1
bne.s .del
* Here need IKBD mode test and store
* Here not really needed
* by other games it may be different !!!
* Prepare fetching code:
lea GameStat+ikbdof+AltRamPos,a4
lea ikbstoc+2(pc),a2
move.l a4,(a2)
* Need to receive status packet:
move.l ikbdsysv(pc),a1
lea my_ikbds(pc),a2
move.l a2,(a1)
pea joysta(pc)
move.w #0,-(sp) *1 byte only to
send
move.w #25,-(sp)
trap #14
addq.l #8,sp
*Some delay * Or solve with counting receives....
move.l #6984,d1
.del2 subq.l #1,d1
bne.s .del2
cmp.b #$00,1(a4) * Normal value
bne.s go_mor3
clr.b (a4)
go_mor3
* Back org ikbdsys vector:
move.l ikbdsysv(pc),a1
lea orgikbds(pc),a2
move.l (a2),(a1)
pea ikbdres(pc) *Back
regular IKBD mode
move.w #1,-(sp)
move.w #25,-(sp)
trap #14
addq.l #8,sp
* Set screen
move.w d7,-(sp)
pea GameScrB
pea GameScrB
move.w #5,-(sp)
trap #14
lea 12(sp),sp
* Write for sure :
lea
NewPhyst,a2
move.l #"PPGX",(a2)+
move.l #MainInb,(a2)
ToDesktop clr.w -(sp)
trap #1
*Regular
exit
* Reading 8-byte packet from IKBD:
my_ikbds
* btst #0,$FFFFFC00.w
* beq.s ikbdpac
movem.l a3-a4,-(sp)
tst.b $FFFFFC00.w
ikbstoc lea
0,a4 *****
lea ikbstoc+2(pc),a3
move.b $FFFFFC02.w,(a4)+
move.l a4,(a3)
movem.l (sp)+,a3-a4
rts *Not rte !
* It was last part of saving gamestate !
ikbdsysv dc.l 0
orgikbds dc.l 0
ikbdres dc.b $80,1
joysta dc.b
$92,0
even
forvs *Sound pattern, simple
dc.b 66,2
dc.b 125,2,80,2
dc.b 1 *Noise perlen -here not used
dc.b %11111000 *Mixer control
dc.b 16,16,16
dc.b 0,22,0
* Detecting HW, RAM
hwdet
bclr
#1,$484.w * Key repeat off !!! Important if using TOS call
for key read
*Check TOS version - may be not built inm, but running in RAM !
move.l $4F2.w,d1
* clr.b
d1 *on round address always
move.l d1,a1
move.b 2(a1),d0 *TOS
ver major
move.b 3(a1),d1 *TOS
ver minor
* Following is necessary to correct if run in low RAM
* in area below launcher
* otherwise Trap #1 will write in code !!!!
* move.l $28(a1),gemdap *
Actual GEMDOS proc.
* Writing TOS version for later outprint
lea machin(pc),a2
move.b d0,(a2)+ *TOS V
move.b d1,(a2)+ *TOS v
move.b 29(a1),4(a2) *Lang
code
*'Detecting' TOS RAM size, just by $42E
move.l $42E,d2
swap d2
lsr.w
#3,d2 *shift so
that 512KB will be 1
move.b d2,(a2)+
*If TOS is 4 or 3 , skip next tests...
cmp.b #4,d0
beq isfalc
cmp.b
#3,d0
beq
istt
* Physical RAM size by MemCTRL sysvar, or by Chip read ...
clr.l d3
*Instead orgphystop look MMU control register shadow $424
move.b $424.w,d3
move.l d3,d2
and.b
#1,d2
move.l d3,d1
and.b
#4,d1
lsr.b
#2,d1
add.b
d1,d2 *512K multiplier - 1 or 2 or 0
move.l
d3,d4
and.b
#2,d4
move.l d3,d1
and.b
#8,d1
lsr.b
#2,d1
add.b
d1,d4 *2M mult. 2 or 4 or 0
lsr.b
#1,d4 *now 1 or 2
clr.l
d3
tst.b
d2
beq.s
seem2
move.l
#$40000,d3 *256KB
lsl.l
d2,d3 *mult by 2 or
4
seem2
clr.l d2
tst.b
d4
beq.s keepms
move.l #$100000,d2
*1MB
lsl.l
d4,d2
add.l d2,d3
keepms swap d3
lsr.w
#3,d3 *shift so
that 512KB will be 1
move.b d3,4(a2)
*Detecting machine HW - is STE, MSTE ?
*Is MSTE ?
move.l sp,a3
lea buser1(pc),a1
move.l 8.w,backorb-buser1+2(a1)
move.l a1,8.w
move.b $FFFF8E21.w,d1
* read from HW reg
*Will do bus error if not Mega STE
move.b #3,(a2)+ *Code for
MSTE
* d1 - bit 0 = cache on/off , bit 1 (?) =
8/16MHz
btst #1,d1
sne (a2)
* After this may set 16MHz by need, or even back to 8...
addq.l #1,a2
move.b #$FF,$FFFF8E21.w
st (a2)
bra.s backorb
buser1 lea buser2(pc),a1
move.l a1,8.w
tst.b $FFFF8924.w *Microwire
for STE detect
move.b #2,(a2) *Code for STE
bra.s restosp
buser2 move.b #1,(a2)
restosp move.l a3,sp
backorb move.l
#0,8.w *here comes original buserror vector
rts
machin dc.b 0,0,0,0,0,0,0,0,0,0
*TOS V Major, TOS v minor, RAM size, HW
* MSTE clock at start, MSTE clock set,
Lang code, Real RAM size
istt move.b #5,(a2) *HW code
rts
*
isfalc move.b #4,(a2) *HW code
*PMMU moving needed because of restore possible difference
...
newpos equ $3FE000
lea
pmmuop(pc),a1
move.b #0,(a1)
clr.l d0
movec cacr,d0
move.w #$20A,d0
movec d0,cacr
lea $700.w,a0
lea newpos,a1
move.w #$100,d0
pmmml move.b (a0)+,(a1)+
dbf d0,pmmml
lea pmmuop+2(pc),a0
pmove.d crp,(a0)
move.l #newpos,4(a0)
pmove.d (a0),crp
lea pmmuop+10(pc),a1
move.l #$FF8707,(a1)
pmove.l (a1),tt0
* Setting CPU caches best for game :
move.w #$809,d7 *
Instr cache on, data off
movec d7,cacr
move.w d7,d2
and.w #1,d2
lsr.w #7,d7
and.w #2,d7
or.w d7,d2
lea falccach(pc),a1
move.b d2,(a1)+
move.b #$CF,(a1) *
Validity flag !
*Setting bus, by game :
and.b
#%11011111,$ffff8007.w *16MHz, STE bus
or.b #%00000001,$FFFF8007.w
rts
pmmuop ds.b 32
falccach dc.w 0
machipr *Outprints machine
parameters
lea hwpos(pc),a0
bsr pmess
lea mait(pc),a0
bsr pmess
lea machin+3(pc),a1
cmp.b #1,(a1)
bne.s isstem
lea hwst(pc),a0
bra.s hwoup
isstem cmp.b #2,(a1)
bne.s ismstem
lea hwste(pc),a0
bra.s hwoup
ismstem cmp.b #3,(a1)
bne.s isfalcm
lea hwmste(pc),a0
bsr pmess
*Outprint CPU clock too if MSTE:
lea machin+4(pc),a1
tst.b (a1)
bne.s sho16 *if begin clock
16 then print 16 only
addq.l #1,a1
tst.b (a1)
beq.s sho8 *if begin and end
is 8 show 8 only
* Show 8>16
lea hwm816m(pc),a0
bra.s hwoup
sho16 lea hwm16m(pc),a0
bra.s hwoup
sho8 lea hwm8m(pc),a0
bra.s hwoup
isfalcm cmp.b #4,(a1)
bne.s seetv
lea hwfalc(pc),a0
hwoup bsr pmess
seetv *TOS version outprint
lea tosvit(pc),a0
bsr pmess
lea tosvp+1(pc),a2
lea machin(pc),a1
move.b (a1)+,d0 *Major
add.b #"0",d0
move.b d0,(a2)
move.b (a1),d1 *Minor
cmp.b #$62,d1 *is TOS 1.62 ?
beq.s t162s
add.b #"0",d1
moveq #"0",d0
bra.s tosvpri
t162s moveq #"6",d0
moveq #"2",d1
tosvpri addq.l #2,a2
move.b d0,(a2)+
move.b d1,(a2)
lea tosvp(pc),a0
bsr pmess
*TOS RAM size outprint
lea ramit(pc),a0
bsr pmess
lea machin+2(pc),a1
cmp.b #1,(a1)
bne.s not512
lea rams512(pc),a0
bra.s ramsoup
not512 *needs some calc...
moveq #0,d1
move.b (a1),d1
lsr.b #1,d1
scs d6 *Flag for half MB at
end
lea ramsiu+1(pc),a1 *Some aligning...
tst.b d6
beq.s bratoa
lea ramsiu(pc),a1
bratoa bsr toasc
tst.b d6
beq.s ramsta
move.b #".",(a1)+
move.b #"5",(a1)
ramsta lea ramsiu(pc),a0
ramsoup bsr.s pmess
* ST RAM size outprint
lea machin+3(pc),a1
cmp.b #5,(a1)
beq.s end_hwpr
cmp.b #4,(a1)
beq.s end_hwpr
lea ramst(pc),a0
bsr pmess
lea machin+7(pc),a1
cmp.b #1,(a1)
bne.s not512rs
lea
rams512(pc),a0
bra.s ramsouprs
not512rs *needs some calc...
moveq #0,d1
move.b (a1),d1
lsr.b #1,d1
scs d6 *Flag for half MB at
end
lea
ramsiu+1(pc),a1 *Some aligning...
tst.b d6
beq.s bratoars
lea ramsiu(pc),a1
bratoars bsr toasc
tst.b d6
beq.s ramstars
move.b #".",(a1)+
move.b #"5",(a1)
ramstars lea ramsiu(pc),a0
ramsouprs bsr.s pmess
end_hwpr
lea noGXp(pc),a0
tst.b gxf
beq.s skip_gxki
lea gamext(pc),a0
skip_gxki bsr pmess
rts
pmess pea (a0)
move.w #9,-(sp)
trap #1
addq.l #6,sp
rts
toasc *cover values from 1 to 14
divu #10,d1
move.b d1,d2
swap d1
add.b #"0",d2 *10s of MB
cmp.b #"0",d2
bne.s putdig1
move.b #" ",d2
putdig1 move.b d2,(a1)+
add.b #"0",d1 *1s of MB
move.b d1,(a1)+
rts
hwst dc.b " ST",0
hwste dc.b " STE",0
hwmste dc.b "Mega STE",0
hwfalc dc.b " Falcon",0
hwm8m dc.b 13,10," 8 MHz",0
hwm16m dc.b 13,10," 16 MHz",0
hwm816m dc.b 13,10,"8>16 MHz",0
tosvp dc.b " 1.00",0
rams512 dc.b " 512 KB",0 * ,27,"H",0
ramsiu dc.b " MB",0
hwpos dc.b 27,"E",27,"Y",48,32,0
homec dc.b 27,"H",0 *Cursor back to top left
* Info texts:
mait dc.b "Machine: ",0
ramit dc.b 13,10,"TOS RAM:",0
ramst dc.b ", ST RAM:",0
tosvit dc.b 13,10,"TOS ver: ",0
gamext dc.b 13,10,13,10,"GAMEX: key F9",27,"H",0
langs dc.b
27,"H","Press E for English,",13,10
dc.b "D for Deutsch",13,10
dc.b "or F for Francais",13,10,0
infstr dc.b 13,10,"Press I for infinite
strength",0
lowRamTM dc.b 13,10,"Too much low RAM occupied !",0
RAMne dc.b 13,10,"Min RAM: 1MB !",0
noGXp dc.b 13,10,13,10,"For Gamex min 2MB RAM
!",27,"H",0
even
* Adding Mega STE and
Falcon machine settings as option :
megastes *see machine
lea machin+3(pc),a2
cmp.b #3,(a2)
beq.s itsMSTE
cmp.b #4,(a2)
beq itsFalc
* return if not MSTE or Falcon :
bra show_hw
itsMSTE
* Mega STE
* Only setting 8/16MHz, together with cache off/on
bsr
clearkb * Clear ikbd buffer for sure
lea mstest(pc),a0
bsr pmess
tst.b machin+5 * Clock
?
bne.s its16m1
lea mste8mt(pc),a0 *
Change txt on screen
bsr pmess
clr.b mstetems
its16m1 move.w #7,-(sp)
trap #1
addq.l #2,sp
cmp.b #"1",d0
beq.s msteset8
cmp.b #"2",d0
beq.s msteset16
cmp.b #" ",d0
beq.s msteexit
cmp.b #13,d0
beq.s mstesetexit
bra.s its16m1
msteset8 lea
mste8mt(pc),a0 * Change txt on screen
bsr pmess
moveq #0,d1
mstecls move.b
d1,mstetems
bra.s its16m1
msteset16 lea
mste16mt(pc),a0 * Change txt on screen
bsr pmess
st d1
bra.s mstecls
mstesetexit * We are in supervisor mode
move.b #$FC,d1
tst.b mstetems
beq.s set8caoff
move.b #$FF,d1
set8caoff move.b
d1,$FFFF8E21.w
addq.b #1,d1
seq machin+5
msteexit bra
show_hw
mstetems dc.b
255,0 *Must preset to on !
mstest dc.b
27,"E"," Mega STE CPU clock setting",13,10
dc.b 13,10,"Press: 1 for 8
MHz, 2 for 16 MHz",13,10
dc.b "Enter for set and
exit",13,10
dc.b "Space exits without change",13,10
dc.b 13,10,13,10,"CPU clock: 16 MHz",0
mste8mt dc.b 27,"Y",39,43,"
8",0
mste16mt dc.b 27,"Y",39,43,"16",0
even
itsFalc * Set bus - CPU, Blitter clock, STE emul.,
CPU instr and Data
cache
bsr
clearkb * Clear ikbd buffer for sure
lea falconst(pc),a0
bsr pmess
* Falcon bus settings:
* FF8007 Bit 0 = CPU clock, Bit 2 = Blitter
clock, Bit 5 = STE bus emul
when = 0 !
move.b $FFFF8007.w,d7
btst #0,d7
bne.s fas1
lea falcc8mt(pc),a0 *
Change txt on screen
bsr pmess
clr.b falset1
fas1 btst #2,d7
bne.s fas2
lea falcb8mt(pc),a0 *
Change txt on screen
bsr pmess
clr.b falset1+1
fas2 btst #5,d7
bne.s fas3
lea falcsten(pc),a0 *
Change txt on screen
bsr pmess
clr.b falset1+2
fas3 move.b falccach(pc),d7
btst #0,d7
*Instr cache
bne.s fas4
lea falcincf(pc),a0 *
Change txt on screen
bsr pmess
clr.b falset1+3
fas4 btst #1,d7
*Data cache
bne.s fas5
lea falcdcf(pc),a0 *
Change txt on screen
bsr pmess
clr.b falset1+4
fas5
move.w #7,-(sp)
trap #1
addq.l #2,sp
cmp.b #"1",d0
beq.s falsetc8
cmp.b #"2",d0
beq.s falsetc16
cmp.b #"3",d0
beq.s falsetb8
cmp.b #"4",d0
beq.s falsetb16
cmp.b #"5",d0
beq falsetsteoff
cmp.b #"6",d0
beq falsetsteon
cmp.b #"7",d0
beq falsetinof
cmp.b #"8",d0
beq falsetinon
cmp.b #"9",d0
beq falsetdaof
cmp.b #"0",d0
beq falsetdaon
cmp.b #" ",d0
beq msteexit
*same exit
cmp.b #13,d0
beq falsetexit
bra.s fas5
falsetc8 lea
falcc8mt(pc),a0 * Change txt on screen
bsr pmess
moveq #0,d1
fal1cls move.b
d1,falset1
bra.s fas5
falsetc16 lea
falcc16mt(pc),a0 * Change txt on screen
bsr pmess
st d1
bra.s fal1cls
falsetb8 lea
falcb8mt(pc),a0 * Change txt on screen
bsr pmess
moveq #0,d1
fal1bls move.b
d1,falset1+1
bra fas5
falsetb16 lea
falcb16mt(pc),a0 * Change txt on screen
bsr pmess
st d1
bra.s fal1bls
falsetsteoff lea
falcstef(pc),a0 * Change txt on screen
bsr pmess
st
d1 * When set, then is off !!!
fal1ste move.b
d1,falset1+2
bra fas5
falsetsteon lea
falcsten(pc),a0 * Change txt on screen
bsr pmess
moveq #0,d1
bra.s fal1ste
falsetinof lea
falcincf(pc),a0 * Change txt on screen
bsr pmess
moveq #0,d1
fal1inc move.b
d1,falset1+3
bra fas5
falsetinon lea
falcincn(pc),a0 * Change txt on screen
bsr pmess
st d1
bra.s fal1inc
falsetdaof lea
falcdcf(pc),a0 * Change txt on
screen
bsr pmess
moveq #0,d1
fal1dac move.b
d1,falset1+4
bra fas5
falsetdaon lea
falcdcn(pc),a0 * Change txt on screen
bsr pmess
st d1
bra.s fal1dac
falsetexit *activate changes :
lea falset1(pc),a3
moveq #0,d3
moveq #0,d4
tst.b (a3) * CPU clock
beq.s fnot1
bset #0,d3
fnot1 addq.l #1,a3
tst.b (a3) * Blitter
clock
beq.s fnot2
bset #2,d3
fnot2 addq.l #1,a3
tst.b (a3) * STE bus
emul
beq.s fnot3
bset #5,d3
fnot3 addq.l #1,a3
tst.b (a3) * Instr.
cache
beq.s fnot4
bset #0,d4
fnot4 addq.l #1,a3
tst.b (a3) * Data cache
beq.s fnot5
bset #1,d4
fnot5 * Now set HW regs :
move.b $FFFF8007.w,d2
and.b #%11011010,d2 *
Mask required bits
or.b d3,d2
move.b d2,$FFFF8007.w
* move.b d3,$FFFF8007.w
move.b d4,falccach
move.b d4,d3
and.w #1,d3
lsl.w #7,d4
and.w #$0100,d4
or.w d3,d4
or.w #$0808,d4 * Clear
order prepare
movec d4,cacr
bra show_hw
falconst dc.b
27,"E"," Falcon bus and cache settings",13,10
dc.b 13,10,"Press: 1 for 8 MHz, 2 for 16 MHz
CPU",13,10
dc.b " 3 for 8
MHz, 4 for 16 MHz Blitter",13,10
dc.b " 5 for not
STE, 6 for STE bus",13,10
dc.b " 7 for
instr. cache off, 8 for on",13,10
dc.b " 9 for
data cache off, 0 for on",13,10
dc.b "Enter for set and
exit",13,10
dc.b "Space exits without change",13,10
dc.b 13,10,13,10,"CPU
clock: 16 MHz"
dc.b 13,10,"Blitter clock: 16 MHz"
dc.b 13,10,"STE
bus: off"
dc.b 13,10,"Instr. cache: on"
dc.b 13,10,"Data
cache: on",0
falcc8mt dc.b 27,"Y",43,47,"
8",0
falcc16mt dc.b 27,"Y",43,47,"16",0
falcb8mt dc.b 27,"Y",44,47,"
8",0
falcb16mt dc.b 27,"Y",44,47,"16",0
falcstef dc.b
27,"Y",45,47,"off",0
falcsten dc.b 27,"Y",45,47," on",0
falcincf dc.b
27,"Y",46,47,"off",0
falcincn dc.b 27,"Y",46,47," on",0
falcdcf dc.b
27,"Y",47,47,"off",0
falcdcn dc.b 27,"Y",47,47," on",0
even
falset1 dc.b 255,255,255,255,255,0
clearkb pea $10002
*Keyboard, Bconstat
trap #13
addq.l #4,sp
tst.b d0
beq.s nocha
pea $20002 *Keyboard,
Bconin
trap #13
addq.l #4,sp
bra.s clearkb
nocha rts
* After displaying Photochrome pic area above will be stack
* area below will be free for TOS, pexec
hwpal *Palette with white #0 and all other as blue
*because of medres/lowres switch bug
dc.w $666,$116,$116,$116,$116,$116,$116,$116
dc.w $116,$116,$116,$116,$116,$116,$116,$116
screnb ds.l 1
picfn dc.b
"CASTLEM.PCH",0 * Unpacked PhotoChrome pic
even
falcpic
include "PCHTOF3.S" *Rutine
which converts PCH to Falcon 16-bit display
photoc
include "PHOTUS.S" * Original
Photochrome Show little reworked
section data
* Workspace for displaying PCH pic :
section bss
head ds.b 6 *PCH header here...
stbitm ds.b 32000
stpal ds.b $4B20
stbm2 ds.b 32000
stpal2 ds.b $4B20
convtbl ds.b 8192