Skip to content

Instantly share code, notes, and snippets.

@htv04
Last active July 24, 2023 20:40
Show Gist options
  • Select an option

  • Save htv04/54f1724887a937304ffd670d4fb37f0f to your computer and use it in GitHub Desktop.

Select an option

Save htv04/54f1724887a937304ffd670d4fb37f0f to your computer and use it in GitHub Desktop.
SGDK Startup Code for VASM
; SGDK Startup Code for VASM v1.0
; By HTV04
; Translated from SEGA Startup Code for the Sozobon C Compiler
; Written by Paul W. Lee
; Modified by Charles Coty
; Modified by Stephane Dallongeville
; MIT License
;
; Copyright (c) 2019 Stephane Dallongeville
; Copyright (c) 2023 HTV04
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
USER_STACK_LENGTH = 512
UTSK_REGS_LEN = 15*4
TSK_PEND_FOREVER = -1
section .text.keepboot
org $00000000
_Start_Of_Rom:
_Vectors_68K:
dc.l __stack ; Stack address
dc.l _Entry_Point ; Program start address
dc.l _Bus_Error
dc.l _Address_Error
dc.l _Illegal_Instruction
dc.l _Zero_Divide
dc.l _Chk_Instruction
dc.l _Trapv_Instruction
dc.l _Privilege_Violation
dc.l _Trace
dc.l _Line_1010_Emulation
dc.l _Line_1111_Emulation
dc.l _Error_Exception,_Error_Exception,_Error_Exception,_Error_Exception
dc.l _Error_Exception,_Error_Exception,_Error_Exception,_Error_Exception
dc.l _Error_Exception,_Error_Exception,_Error_Exception,_Error_Exception
dc.l _Error_Exception
dc.l _INT
dc.l _EXTINT
dc.l _INT
dc.l hintCaller
dc.l _INT
dc.l _VINT
dc.l _INT
dc.l _trap_0 ; Resume supervisor task
dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT
dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
rom_header::
incbin "out/rom_head.bin",0,$100
_Entry_Point:
move #$2700,sr
tst.l $a10008
bne.s SkipJoyDetect
tst.w $a1000c
SkipJoyDetect:
bne.s SkipSetup
lea Table,a5
movem.w (a5)+,d5-d7
movem.l (a5)+,a0-a4
; Check Version Number
move.b -$10ff(a1),d0
andi.b #$0f,d0
beq.s WrongVersion
; Sega Security Code (SEGA)
move.l #$53454741,$2f00(a1)
WrongVersion:
; Read from the control port to cancel any pending read/write command
move.w (a4),d0
; Configure a USER_STACK_LENGTH bytes user stack at bottom, and system stack on top of it
move sp,usp
sub #USER_STACK_LENGTH,sp
move.w d7,(a1)
move.w d7,(a2)
; Jump to initialisation process now...
jmp _start_entry
SkipSetup:
jmp _reset_entry
Table:
dc.w $8000,$3fff,$0100
dc.l $A00000,$A11100,$A11200,$C00000,$C00004
; Interrupt functions
registersDump:
move.l d0,registerState+0
move.l d1,registerState+4
move.l d2,registerState+8
move.l d3,registerState+12
move.l d4,registerState+16
move.l d5,registerState+20
move.l d6,registerState+24
move.l d7,registerState+28
move.l a0,registerState+32
move.l a1,registerState+36
move.l a2,registerState+40
move.l a3,registerState+44
move.l a4,registerState+48
move.l a5,registerState+52
move.l a6,registerState+56
move.l a7,registerState+60
rts
busAddressErrorDump:
move.w 4(sp),ext1State
move.l 6(sp),addrState
move.w 10(sp),ext2State
move.w 12(sp),srState
move.l 14(sp),pcState
jmp registersDump
exception4WDump:
move.w 4(sp),srState
move.l 6(sp),pcState
move.w 10(sp),ext1State
jmp registersDump
exceptionDump:
move.w 4(sp),srState
move.l 6(sp),pcState
jmp registersDump
_Bus_Error:
jsr busAddressErrorDump
movem.l d0-d1/a0-a1,-(sp)
move.l busErrorCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Address_Error:
jsr busAddressErrorDump
movem.l d0-d1/a0-a1,-(sp)
move.l addressErrorCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Illegal_Instruction:
jsr exception4WDump
movem.l d0-d1/a0-a1,-(sp)
move.l illegalInstCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Zero_Divide:
jsr exceptionDump
movem.l d0-d1/a0-a1,-(sp)
move.l zeroDivideCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Chk_Instruction:
jsr exception4WDump
movem.l d0-d1/a0-a1,-(sp)
move.l chkInstCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Trapv_Instruction:
jsr exception4WDump
movem.l d0-d1/a0-a1,-(sp)
move.l trapvInstCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Privilege_Violation:
jsr exceptionDump
movem.l d0-d1/a0-a1,-(sp)
move.l privilegeViolationCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Trace:
jsr exceptionDump
movem.l d0-d1/a0-a1,-(sp)
move.l traceCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Line_1010_Emulation:
_Line_1111_Emulation:
jsr exceptionDump
movem.l d0-d1/a0-a1,-(sp)
move.l line1x1xCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_Error_Exception:
jsr exceptionDump
movem.l d0-d1/a0-a1,-(sp)
move.l errorExceptionCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_INT:
movem.l d0-d1/a0-a1,-(sp)
move.l intCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_EXTINT:
movem.l d0-d1/a0-a1,-(sp)
move.l eintCB,a0
jsr (a0)
movem.l (sp)+,d0-d1/a0-a1
rte
_VINT:
btst #5,(sp) ; Skip context switch if not in user task
bne.s no_user_task
tst.w task_lock
bne.s lock
move.w #0,-(sp) ; TSK_superPend() will return 0
bra.s unlock ; If lock == 0, supervisor task is not locked
lock:
bcs.s no_user_task ; If lock < 0, super is locked with infinite wait
subq.w #1,task_lock ; Locked with wait, subtract 1 to the frame count
bne.s no_user_task ; And do not unlock if we did not reach 0
move.w #1,-(sp) ; TSK_superPend() will return 1
unlock:
; Save bg task registers (excepting a7, that is stored in usp)
move.l a0,task_regs
lea (task_regs+UTSK_REGS_LEN),a0
movem.l d0-d7/a1-a6,-(a0)
move.w (sp)+,d0 ; Load return value previously pushed to stack
move.w (sp)+,task_sr ; Pop user task sr and pc, and save them,
move.l (sp)+,task_pc ; so they can be restored later.
movem.l (sp)+,d2-d7/a2-a6 ; Restore non clobberable registers
no_user_task:
; At this point, we always have in the stack the SR and PC of the task
; we want to jump after processing the interrupt, that might be the
; point where we came from (if there is no context switch) or the
; supervisor task (if we unlocked it).
movem.l d0-d1/a0-a1,-(sp)
ori.w #$0001,intTrace ; in V-Int
addq.l #1,vtimer ; increment frame counter (more a vint counter)
btst #3,VBlankProcess+1 ; PROCESS_XGM_TASK ? (use VBlankProcess+1 as btst is a byte operation)
beq.s no_xgm_task
jsr XGM_doVBlankProcess ; do XGM vblank task
no_xgm_task:
btst #1,VBlankProcess+1 ; PROCESS_BITMAP_TASK ? (use VBlankProcess+1 as btst is a byte operation)
beq.s no_bmp_task
jsr BMP_doVBlankProcess ; do BMP vblank task
no_bmp_task:
move.l vintCB,a0 ; load user callback
jsr (a0) ; call user callback
andi.w #$FFFE,intTrace ; out V-Int
movem.l (sp)+,d0-d1/a0-a1
rte
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment