;* ;* JAVA VIRTUAL MACHINE FOR APPLE II PRODOS ;* .INCLUDE "global.inc" .INCLUDE "class.inc" .IMPORT UTIL_INIT,HOME,GETLN,PRSTR,PRSTRLN,PRHSTRLN,COUT,CROUT,PUTS,PRBYTE,KBWAIT,MEMSRC,MEMDST,MEMCPY .IMPORT HMEM_INIT,HMEM_ALLOC,HMEM_FREE .IMPORT HMEM_PTR,HMEM_REF_INC,HMEM_REF_DEC,HMEM_LOCK,HMEM_GC .IMPORT HSTR_INIT,STR_HASH,HSTR_HASH,HSTRPL_ADD,HSTRPL_DEL .IMPORT LOADCLASS_INIT,IO_INIT,IODEV_INIT,VBL_INIT .IMPORT HCLASS_INIT,HCLASS_NAME,HCLASS_HNDL,CLASS_MATCH_NAME,CLASS_MATCH_DESC .IMPORT RESOLVE_CLASS,RESOLVE_METHOD,CLASS_METHODPTR .IMPORT SYSCLASS_INIT,EXCEPT_INIT,SYS_CALL .IMPORT HMAINNAMESTR,HMAINDESCSTR .IMPORT THREAD_INIT,THREAD_NEW,THREAD_SETRUN,THREAD_YIELD .IMPORT ITHREAD_PUSH_SP,ITHREAD_PUSH_TLS,LOADEXECSTATE,BEST_THREAD .IMPORT INTERP_INIT,INTERP_END,DVM_INIT .IMPORT CLASSPREFIX,PREFIX_SET,FILE_GETINFO,FILE_OPEN,FILE_CLOSE,FILE_SETBUFFER,FILE_BLOAD .IFDEF SWAPPING .IMPORT HMEM_SWAP_CLEANUP .ENDIF .EXPORT INIT_START,VM_RESTART,WARM_INIT .IFDEF DEBUG .IMPORT HMEM_DUMP,HSTRPL_DUMP .ENDIF PARSELEN EQU $A0 .SEGMENT "INIT" INIT_START: VM_WARMINIT: DEC WARM_INIT LDX #$9E ; DEVICE CTRL CALL FUNC INDEX : STX DEVSLOT TXA ; CONVERT TO SLOT # LSR AND #$07 ORA #IOCTL_DEACTIVATE TAY SEI ; DISABLE INTERRUPTS JSR DEVCALL ; DEACTIVATE DEVICES CLI LDX DEVSLOT DEX DEX CPX #$90 BNE :- PSTRLN "" ; I HAVE NO IDEA WHY THIS IS NEEDED LDX #$FF ; RESET STACK TXS LDA CHAIN_CMD ; NO PASSED IN PARAMS PHA .IF 0 BNE :+ PSTR "PRESS ESC TO REBOOT, RETURN TO CONTINUE." JSR KBWAIT CMP #$9B BNE :+ JSR PRODOS .BYTE $41 ; DE-ALLOC INTERRUPT .ADDR DEALLOCINTPARMS BIT ROMIN ; SWAP ROM IN LDA #$00 STA $3F4 ; INVALIDATE POWER-UP BYTE JMP ($FFFC) ; RESET : JSR CROUT .ENDIF JMP SKIPBANNER ; ; INITIALIZE SYSTEM ; VM_INIT: LDA #$00 STA $3F4 ; INVALIDATE POWER-UP BYTE LDX #$F0 ; CLEAR LINK TABLE LDA #$00 : DEX STA LINK_TABLE,X BNE :- JSR IO_INIT JSR HOME .IFDEF BIGMEM PSTR "VM02 128K" .ELSE PSTR "VM02 64K" .ENDIF .IFDEF FLOATING_POINT PSTR " Floating Point" .ENDIF PSTRLN " Version 1.0" PSTRLN "Copyright 2010, David Schmenk" ; PSTRLN "'EXIT' to reboot" SKIPBANNER: .IFDEF DEBUG PSTRLN "DEBUG ENABLED" LDA #$69 ; PLACE FENCE AT BOTTOM OF STACK STA $0100 STA $0101 .ENDIF .IFDEF DEBUG_DUMP LDA #$00 ; TURN ON DEBUG SLOT STA CSWL LDA #$C0|DEBUG_DUMP STA CSWH .ENDIF LDA #$4C ; JMP INSTRUCTION STA OPJMP LDA #VM_RESTART STA LINK_EXIT+1 LDA #VM_REBOOT STA LINK_REBOOT+1 JSR UTIL_INIT JSR HMEM_INIT JSR IODEV_INIT JSR HSTR_INIT JSR HCLASS_INIT JSR THREAD_INIT JSR EXCEPT_INIT JSR INTERP_INIT JSR DVM_INIT JSR LOADCLASS_INIT SEI ; DISABLE INTERRUPTS BIT LCBNK2 ; MAKE SURE LCBANK2 SET UP BIT LCBNK2 CLI JSR SYSCLASS_INIT ; ; LOOK FOR STARTUP FILE IN INPUT BUFFER ($01FF = LEN OF STARTUP STRING) ; PLA BEQ :+ TAX BNE PARSECMD : LDA #STARTUP JSR FILE_GETINFO BCS CMDLINE ; NOPE, INPUT COMMAND LINE LDA #$00 PHA STA PARSELEN LDA #STARTUP JMP SETRUNCLASS ; ; PROMPT FOR MAIN CLASS ; CMDLINE: PSTR "Main class" LDA #':'|$80 STA PROMPTCHAR JSR GETLN CPX #$00 BEQ CMDLINE PARSECMD: STX PARSELEN : LDA $0200,X ; STRIP OFF HIGH BITS AND #$7F STA $0200,X DEX BPL :- LDX #$00 JSR PARSELINE TXA BEQ CMDLINE PHA ; CLEVERLY PUT STRING LENGTH LDA #$FF ; IN FRONT OF INPUT BUFFER AT $200 LDX #$01 SETRUNCLASS: JSR HSTRPL_ADD STA RUNCLASS STX RUNCLASS+1 .IFDEF DEBUG_PARAMS JSR PRHSTRLN JSR KBWAIT .ENDIF PARSEARGS: PLA BEQ :+ TAX JSR PARSELINE TXA BEQ :+ PHA LDA #$FF LDX #$01 JSR HSTRPL_ADD STY TMP LDY NARGS STA HARGSL,Y TXA STA HARGSH,Y LDA TMP STA ARGSHASH,Y INC NARGS BNE PARSEARGS : LDA NARGS ; ALLOCATE ARGS ARRAY ASL ASL CLC ADC #$02 LDX #$00 LDY #$00 JSR HMEM_ALLOC STA HARGS STX HARGS+1 JSR HMEM_PTR STA $A0 STX $A1 LDY #$00 LDA NARGS STA ($A0),Y TYA TAX INY STA ($A0),Y LDA NARGS BEQ RUNMAIN INY FILLARGS: LDA HARGSL,X STA ($A0),Y INY LDA HARGSH,X STA ($A0),Y INY LDA #CL_STR STA ($A0),Y INY LDA ARGSHASH,X STA ($A0),Y INY INX DEC NARGS BNE FILLARGS RUNMAIN: JSR VBL_INIT ; TURN VBL IRQS ON IF PRESSENT LDA #$00 BIT CLRKBD ; CLEAR KEYBOARD STA TYPEBUFFLEN ; FLUSH INPUT BUFFER STA CHAIN_CMD ; CLEAR CHAIN COMMAND TAX JSR THREAD_NEW ; NEED TO CREATE THREAD INSTANCE OBJECT LDA #T_REF LDX #CL_ARRAY JSR ITHREAD_PUSH_SP ; PUSH MAIN PARAM ON STACK LDA HARGS+1 LDX HARGS JSR ITHREAD_PUSH_SP LDA HMAINNAMESTR ; RUN MAIN METHOD LDX HMAINNAMESTR+1 JSR ITHREAD_PUSH_SP LDA HMAINDESCSTR LDX HMAINDESCSTR+1 JSR ITHREAD_PUSH_SP LDA RUNCLASS ; RETRIEVE CLASS NAME LDX RUNCLASS+1 JSR ITHREAD_PUSH_SP JSR THREAD_SETRUN STY BEST_THREAD JSR LOADEXECSTATE ; JUMP TO SCHEDULER PERR "OOPS, RETURN FROM YIELD" BRK LDA INTERP_END ; DUMMY READ TO MAKE EXTERN SHOW UP IN MAP FILE PARSELINE: LDY #$00 ; SKIP PREVIOUS STRING LDA INQUOTE BEQ :+ DEC INQUOTE INX : LDA PARSELEN STX PARSELEN SEC SBC PARSELEN STA PARSELEN BNE SKIPPREV PARSEDONE: LDX #$00 RTS SKIPPREV: LDA $0200,X STA $0200,Y INY INX BPL SKIPPREV LDX #$00 SKIPSPACE: LDA $0200 CMP #'"' BEQ PARSEQUOTE CMP #' '+1 ; CHECK FOR WHITESPACE BCS PARSESTR DEC PARSELEN BEQ PARSEEXIT : LDA $0201,X ; SHIFT BUFFER DOWN STA $0200,X INX BPL :- LDX #$00 BEQ SKIPSPACE PARSESTR: INX CPX PARSELEN BEQ PARSEEXIT LDA $0200,X CMP #' '+1 BCS PARSESTR PARSEEXIT: RTS PARSEQUOTE: DEC PARSELEN : LDA $0201,X ; SKIP QUOTE CHAR STA $0200,X INX BPL :- LDX #$FF FINDQUOTE: INX CPX PARSELEN BEQ PARSEEXIT LDA $0200,X CMP #'"' BNE FINDQUOTE INC INQUOTE RTS DEVCALL: .BYTE $6C DEVSLOT: .BYTE $92,$03 STARTUP: .BYTE 7,"STARTUP" RUNCLASS: .WORD $0000 NARGS: .BYTE $00 INQUOTE: .BYTE $00 HARGSL: .RES 10 HARGSH: .RES 10 ARGSHASH: .RES 10 HARGS: .WORD $0000 WARM_INIT: .BYTE $00 DEALLOCINTPARMS: .BYTE $01 .BYTE $00 ; INT NUM .CODE ;* ;* MAIN ENTRYPOINT ;* ; ORG $1000 VM_STARTUP: JMP VM_INIT ;* ;* ALL THREADS ARE DONE, OR AN UNRECOVERABLE ERROR OCCURED ;* EXIT TO PRODOS ;* VM_RESTART: STA EXIT_STATUS ; SAVE EXIT STATUS STX EXIT_STATUS+1 LDX #$05 ; CLOSE ALL OPEN FILES : LDA LINK_OPENFILES,X BEQ :+ STX ACNT TAY JSR FILE_CLOSE LDX ACNT : DEX BPL :-- LDA #CLASSPREFIX JSR PREFIX_SET LDA #$00 LDX #$10 JSR FILE_SETBUFFER LDA #VM02FILE JSR FILE_BLOAD .IFDEF SWAPPING JSR HMEM_SWAP_CLEANUP ; CALL CLEANUP IN INIT SECTION - TOO COOL .ENDIF JMP VM_WARMINIT ; WARM INIT VM_REBOOT: SEI DEC $3F4 ; INVALIDATE POWER-UP BYTE BIT ROMIN ; SWAP ROM IN JMP ($FFFC) ; RESET .DATA .IFDEF BIGMEM VM02FILE: .BYTE 5,"VM02E" .ELSE VM02FILE: .BYTE 4,"VM02" .ENDIF