; E04-S07: compile COUNTER.N8, assign final code addresses, and write two ; deterministic PRGs. The generated code runs from the PRG in a second x128 ; session; the fixture-owned wrapper places FRAME_FP and reports the program's ; `total` local through the mailbox. .setcpu "6502" .include "../../src/common/c128.inc" .include "../../src/common/mailbox.inc" .include "../../src/common/formats.inc" .include "../../src/common/frames.inc" .import mmu_init, mmu_bank0, mmu_shutdown .import src_load, src_dos_code, src_kernal_err .import names_init .import diag_init, diag_finish, diag_screen .import parse_file_sized .import em_on, em_bad .import cg_code, cg_len, cg_err .import fl_err .import sz_plan_code, sz_code_base .import sz_mismatch .import out_begin, out_section, out_end_section, out_byte, out_bytes .import out_finish, out_abort, out_load, out_entry, out_start, out_err .import gen_stub FRAME_BASE = $BF80 ; software frame area under CR=$0E WRAPPER_LEN = 66 CODE_ADDR = PRG_ENTRY_ADDR + WRAPPER_LEN .macro ON_CARRY target bcc :+ jmp target : .endmacro .macro ON_NONZERO target beq :+ jmp target : .endmacro .segment "LOADADDR" .word $1C01 .segment "EXEHDR" .word basic_end .word 10 .byte $9E .byte "7181" .byte $00 basic_end: .word $0000 .segment "MAILBOX" .res MB_SIZE .segment "STARTUP" .export test_entry test_entry: php sei ldx #MB_SIZE - 1 lda #$00 @clr: sta MB_BASE,x dex bpl @clr lda #MB_MAGIC0_VALUE sta MB_MAGIC0 lda #MB_MAGIC1_VALUE sta MB_MAGIC1 lda #MB_PROD_COMPILER sta MB_PRODUCER lda #MB_ST_RUNNING sta MB_STATUS jsr mmu_init jsr mmu_bank0 lda #name_src ldy #name_src_len jsr src_load cmp #$00 ON_NONZERO fail_load ; src_load returns A=0 on success jsr names_init lda #name_src ldy #name_src_len jsr diag_init lda #$00 sta diag_screen lda #$01 sta em_on lda #PRG_LOAD_ADDR sta out_load+1 lda #PRG_ENTRY_ADDR sta out_entry+1 lda #WRAPPER_LEN jsr sz_plan_code ; final code base for absolute fixups jsr parse_file_sized jsr diag_finish sta diag_count lda diag_count sta MB_DATA+0 lda em_bad sta MB_DATA+1 lda cg_len sta MB_DATA+2 lda cg_err sta MB_DATA+3 lda fl_err sta MB_DATA+4 lda sz_mismatch sta MB_DATA+6 lda diag_count ON_NONZERO fail_diag lda em_bad ON_NONZERO fail_emit lda cg_err ON_NONZERO fail_emit lda fl_err ON_NONZERO fail_emit lda #name_counter sta out_name_ptr+1 lda #name_counter_len sta out_name_len jsr emit_output bcs fail_out lda #name_countb sta out_name_ptr+1 lda #name_countb_len sta out_name_len jsr emit_output bcs fail_out lda #MB_ST_PASS sta MB_STATUS jmp done fail_diag: lda #2 jmp fail_common fail_emit: lda #3 jmp fail_common fail_out: lda emit_err sta MB_DATA+5 lda #4 jmp fail_common fail_load: sta MB_DATA+5 lda src_dos_code sta MB_DATA+6 lda src_kernal_err sta MB_DATA+7 lda #1 fail_common: sta MB_CODE lda #$00 sta MB_CODE+1 lda #MB_ST_FAIL sta MB_STATUS done: jsr mmu_shutdown plp rts ; Write one output pair with the same generated bytes. A/X = base name, ; out_name_len = length. C=1 on any output failure. emit_output: lda out_name_ptr ldx out_name_ptr+1 ldy out_name_len jsr out_begin ON_CARRY out_fail lda #PRG_LOAD_ADDR sta out_start+1 lda #sec_stub ldy #4 jsr out_section ON_CARRY out_fail lda #gen_stub ldy #PRG_STUB_SIZE jsr out_bytes ON_CARRY out_fail jsr out_end_section ON_CARRY out_fail lda #PRG_ENTRY_ADDR sta out_start+1 lda #sec_start ldy #5 jsr out_section ON_CARRY out_fail lda #wrapper ldy #WRAPPER_LEN jsr out_bytes ON_CARRY out_fail jsr out_end_section ON_CARRY out_fail lda sz_code_base sta out_start lda sz_code_base+1 sta out_start+1 lda #sec_code ldy #4 jsr out_section ON_CARRY out_fail lda #cg_code ldy cg_len jsr out_bytes ON_CARRY out_fail jsr out_end_section ON_CARRY out_fail jsr out_finish ON_CARRY out_fail clc rts out_fail: lda out_err sta emit_err jsr out_abort sec rts ; The PRG's fixed entry, at $1C0D. It clears the mailbox, installs a frame ; base, calls the generated program body at CODE_ADDR, and reports `total` ; (the second local, FP-2) as MB_DATA. wrapper: lda $FF00 ; save CR, select RAM through $BFFF pha lda #$0E sta $FF00 ldx #MB_SIZE - 1 lda #$00 @clr: sta MB_BASE,x dex bpl @clr lda #MB_MAGIC0_VALUE sta MB_MAGIC0 lda #MB_MAGIC1_VALUE sta MB_MAGIC1 lda #MB_PROD_PROGRAM sta MB_PRODUCER lda #MB_ST_RUNNING sta MB_STATUS lda #FRAME_BASE sta FRAME_FP+1 jsr CODE_ADDR lda FRAME_BASE - 3 sta MB_DATA pla sta $FF00 ; restore the BASIC entry mapping lda #MB_ST_PASS sta MB_STATUS rts .assert * - wrapper = WRAPPER_LEN, error, "counter wrapper length changed" .assert CODE_ADDR < $4000, error, "generated code must stay below BASIC ROM" .segment "ZEROPAGE" out_name_ptr: .res 2 .segment "RODATA" name_src: .byte "COUNTER.N8" name_src_len = * - name_src name_counter: .byte "COUNTER" name_counter_len = * - name_counter name_countb: .byte "COUNTB" name_countb_len = * - name_countb sec_stub: .byte "STUB" sec_start: .byte "START" sec_code: .byte "CODE" .segment "BSS" diag_count: .res 1 out_name_len: .res 1 emit_err: .res 1