use Util.Macs.s use Load.Macs.s use Locator.Macs.s use Mem.Macs.s use Misc.Macs.s use Tool222.MACS.s use Core.MACS.s use .\Defs.s ; Feature flags NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging NO_MUSIC equ 1 ; turn music + tool loading off ; External data provided by the main program segment tiledata EXT ; Sprite plane data and mask banks are provided as an exteral segment spritedata EXT spritemask EXT ; IF there are overlays, they are provided as an external Overlay EXT ; Core engine functionality. The idea is that that source file can be PUT into ; a main source file and all of the functionality will be available. ; ; There are some constancts that must be externally defined that can affect how ; the GTE runtime works ; ; NO_MUSIC : Set to non-zero to avoid using any source ; NO_INTERRUPTS : Set to non-zero to avoid installing custom interrupt handlers mx %00 ; High-Level StartUp and ShutDown functions EngineStartUp ENT phb phk plb jsr ToolStartUp ; Start up the toolbox tools we rely on jsr _CoreStartUp plb rtl _CoreStartUp jsr SoundStartUp ; Start up any sound/music tools jsr IntStartUp ; Enable certain iterrupts jsr InitMemory ; Allocate and initialize memory for the engine jsr EngineReset ; All of the resources are allocated, put the engine in a known state jsr InitGraphics ; Initialize all of the graphics-related data nop jsr InitSprites ; Initialize the sprite subsystem jsr InitTiles ; Initialize the tile subsystem jsr InitTimers ; Initialize the timer subsystem rts EngineShutDown ENT phb phk plb jsr _CoreShutDown jsr ToolShutDown plb rtl _CoreShutDown jsr IntShutDown jsr SoundShutDown rts ToolStartUp _TLStartUp ; normal tool initialization pha _MMStartUp _Err ; should never happen pla sta MasterId ; our master handle references the memory allocated to us ora #$0100 ; set auxID = $01 (valid values $01-0f) sta UserId ; any memory we request must use our own id _MTStartUp rts MasterId ds 2 UserId ds 2 ; Fatal error handler invoked by the _Err macro PgmDeath tax pla inc phx phk pha bra ContDeath PgmDeath0 pha pea $0000 pea $0000 ContDeath ldx #$1503 jsl $E10000 ToolShutDown rts ; Use Tool222 (NinjaTrackerPlus) for music playback SoundStartUp lda #NO_MUSIC bne :no_music pea $00DE pea $0000 _LoadOneTool _Err lda UserId pha _NTPStartUp :no_music rts SoundShutDown lda #NO_MUSIC bne :no_music _NTPShutDown :no_music rts ; Install interrupt handlers. We use the VBL interrupt to keep animations ; moving at a consistent rate, regarless of the rendered frame rate. The ; one-second timer is generally just used for counters and as a handy ; frames-per-second trigger. IntStartUp lda #NO_INTERRUPTS bne :no_interrupts PushLong #0 pea $0015 ; Get the existing 1-second interrupt handler and save _GetVector PullLong OldOneSecVec pea $0015 ; Set the new handler and enable interrupts PushLong #OneSecHandler _SetVector pea $0006 _IntSource PushLong #VBLTASK ; Also register a Heart Beat Task _SetHeartBeat :no_interrupts rts IntShutDown lda #NO_INTERRUPTS bne :no_interrupts pea $0007 ; disable 1-second interrupts _IntSource PushLong #VBLTASK ; Remove our heartbeat task _DelHeartBeat pea $0015 PushLong OldOneSecVec ; Reset the interrupt vector _SetVector :no_interrupts rts ; Interrupt handlers. We install a heartbeat (1/60th second and a 1-second timer) OneSecHandler mx %11 phb pha phk plb rep #$20 inc OneSecondCounter sep #$20 ldal $E0C032 and #%10111111 ;clear IRQ source stal $E0C032 pla plb clc rtl mx %00 OneSecondCounter ENT dw 0 OldOneSecVec ds 4 VBLTASK hex 00000000 dw 0 hex 5AA5 ; Reset the engine to a known state ; Blitter initialization EngineReset stz ScreenHeight stz ScreenWidth stz ScreenY0 stz ScreenY1 stz ScreenX0 stz ScreenX1 stz ScreenTileHeight stz ScreenTileWidth stz StartX stz OldStartX stz StartXMod164 stz StartY stz OldStartY stz StartYMod208 stz EngineMode stz DirtyBits stz LastPatchOffset stz BG1StartX stz BG1StartXMod164 stz BG1StartY stz BG1StartYMod208 stz BG1OffsetIndex stz BG0TileOriginX stz BG0TileOriginY stz OldBG0TileOriginX stz OldBG0TileOriginY stz BG1TileOriginX stz BG1TileOriginY stz OldBG1TileOriginX stz OldBG1TileOriginY stz TileMapWidth stz TileMapHeight stz TileMapPtr stz TileMapPtr+2 stz FringeMapPtr stz FringeMapPtr+2 stz BG1TileMapWidth stz BG1TileMapHeight stz BG1TileMapPtr stz BG1TileMapPtr+2 stz SCBArrayPtr stz SCBArrayPtr+2 stz OneSecondCounter ]step equ 0 lup 13 ldx #BlitBuff lda #^BlitBuff ldy #]step jsr BuildBank ]step equ ]step+4 --^ rts ; Allow the user to dynamically select one of the pre-configured screen sizes, or pass ; in a specific width and height. The screen is automatically centered. If this is ; not desired, then SetScreenRect should be used directly ; ; 0. Full Screen : 40 x 25 320 x 200 (32,000 bytes (100.0%)) ; 1. Sword of Sodan : 34 x 24 272 x 192 (26,112 bytes ( 81.6%)) ; 2. ~NES : 32 x 25 256 x 200 (25,600 bytes ( 80.0%)) ; 3. Task Force : 32 x 22 256 x 176 (22,528 bytes ( 70.4%)) ; 4. Defender of the World : 35 x 20 280 x 160 (22,400 bytes ( 70.0%)) ; 5. Rastan : 32 x 20 256 x 160 (20,480 bytes ( 64.0%)) ; 6. Game Boy Advanced : 30 x 20 240 x 160 (19,200 bytes ( 60.0%)) ; 7. Ancient Land of Y's : 36 x 16 288 x 128 (18,432 bytes ( 57.6%)) ; 8. Game Boy Color : 20 x 18 160 x 144 (11,520 bytes ( 36.0%)) ; 9. Agony (Amiga) : 36 x 24 288 x 192 (27,648 bytes ( 86.4%)) ; ; X = mode number OR width in pixels (must be multiple of 2) ; Y = height in pixels (if X > 8) ScreenModeWidth dw 320,272,256,256,280,256,240,288,160,320 ScreenModeHeight dw 200,192,200,176,160,160,160,128,144,1 SetScreenMode ENT phb phk plb jsr _SetScreenMode plb rtl _SetScreenMode cpx #9 bcs :direct ; if x > 8, then assume X and Y are the dimensions txa asl tax ldy ScreenModeHeight,x lda ScreenModeWidth,x tax :direct cpy #201 bcs :exit cpx #321 bcs :exit txa lsr pha ; Save X (width / 2) and Y (height) phy lda #160 ; Center the screen sec sbc 3,s lsr xba pha ; Save half the origin coordinate lda #200 sec sbc 3,s ; This is now Y because of the PHA above lsr ora 1,s plx ; Throw-away to pop the stack ply plx jsr SetScreenRect jmp FillScreen ; tail return :exit rts WaitForKey sep #$20 stal KBD_STROBE_REG ; clear the strobe :WFK ldal KBD_REG bpl :WFK rep #$20 and #$007F rts ClearKbdStrobe sep #$20 stal KBD_STROBE_REG rep #$20 rts ; Read the keyboard and paddle controls and return in a game-controller-like format LastKey db 0 ReadControl ENT jsr _ReadControl rtl _ReadControl pea $0000 ; low byte = key code, high byte = %------AB sep #$20 ldal OPTION_KEY_REG ; 'B' button and #$80 beq :BNotDown lda #PAD_BUTTON_B ora 2,s sta 2,s :BNotDown ldal COMMAND_KEY_REG and #$80 beq :ANotDown lda #PAD_BUTTON_A ora 2,s sta 2,s :ANotDown ldal KBD_STROBE_REG ; read the keyboard bit #$80 beq :KbdNotDwn ; check the key-down status and #$7f ora 1,s sta 1,s cmpl LastKey beq :KbdDown stal LastKey lda #PAD_KEY_DOWN ; set the keydown flag ora 2,s sta 2,s bra :KbdDown :KbdNotDwn lda #0 stal LastKey :KbdDown rep #$20 pla rts put Memory.s put Graphics.s put Sprite.s put Sprite2.s put Render.s put Timer.s put Script.s put blitter/Blitter.s put blitter/Horz.s put blitter/PEISlammer.s put blitter/Tables.s put blitter/Template.s put blitter/Tiles.s put blitter/Tiles00000.s ; normal tiles put blitter/Tiles00001.s ; dynamic tiles put blitter/Tiles00010.s ; normal masked tiles put blitter/Tiles00011.s ; dynamic masked tiles put blitter/Tiles10000.s ; normal tiles + sprites put blitter/Tiles10001.s ; dynamic tiles + sprites put blitter/Tiles10010.s ; normal masked tiles + sprites put blitter/Tiles10011.s ; dynamic masked tiles + sprites put blitter/Tiles11000.s ; normal high priority tiles + sprites put blitter/Tiles11001.s ; dynamic high priority tiles + sprites put blitter/Tiles11010.s ; normal high priority masked tiles + sprites put blitter/Tiles11011.s ; dynamic high priority masked tiles + sprites put blitter/TilesBG1.s put blitter/Vert.s put blitter/BG0.s put blitter/BG1.s put blitter/SCB.s put TileMap.s