; E04-S05: compile hello.n8 and emit a runnable PRG (x128). ; ; The fixture runs in the compiler mapping, loads HELLO.N8, parses and ; type-checks it normally, and reads the single string print captured during ; pass 2. It then writes HELLO.PRG with output.s: the standard BASIC stub at ; $1C01 and a body at $1C0D that saves CR, selects the D129 mapping ($0E), ; prints the captured bytes through CHROUT, restores CR, and returns to BASIC. ; ; This is a bounded source-to-code proof, not the general statement emitter: ; one string print is required and gen_bad rejects anything else. ; ; Mailbox data: +0 diagnostics, +1 print count, +2 gen_bad, +3 text length, ; +4 out_err. FAIL code is the stage: 1 load, 2 diagnostics, 3 unsupported ; print, 4 output. .setcpu "6502" .include "../../src/common/c128.inc" .include "../../src/common/mailbox.inc" .include "../../src/common/formats.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, gen_text, gen_text_len, gen_print_count, gen_bad .import out_begin, out_section, out_end_section .import out_byte, out_bytes, out_finish, out_abort .import out_load, out_entry, out_start, out_err .import gen_stub ; A conditional branch to a far error path: near branch over an absolute JMP. .macro ON_CARRY target bcc :+ 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 lda #$00 sta MB_DATA sta MB_DATA+1 sta MB_DATA+2 sta MB_DATA+3 sta MB_DATA+4 sta MB_DATA+5 sta MB_DATA+6 sta MB_DATA+7 jsr mmu_init jsr mmu_bank0 lda #PRG_LOAD_ADDR sta out_load+1 lda #PRG_ENTRY_ADDR sta out_entry+1 lda #name_src ldy #name_src_len jsr src_load cmp #$00 bne @fail_load jsr names_init lda #name_src ldy #name_src_len jsr diag_init lda #$00 ; ERR files only; keep the screen quiet sta diag_screen jsr parse_file jsr diag_finish sta diag_count lda diag_count sta MB_DATA+0 lda gen_print_count sta MB_DATA+1 lda gen_bad sta MB_DATA+2 lda gen_text_len sta MB_DATA+3 lda diag_count bne @fail_diag lda gen_bad bne @fail_gen lda gen_print_count cmp #1 bne @fail_gen lda gen_text_len beq @fail_gen jsr emit_hello bcc @ok lda emit_err sta MB_DATA+4 lda #4 jmp @fail @ok: lda out_err sta MB_DATA+4 lda #MB_ST_PASS sta MB_STATUS jmp @done @fail_load: sta MB_DATA+5 ; src_load result lda src_dos_code sta MB_DATA+6 lda src_kernal_err sta MB_DATA+7 lda #1 jmp @fail @fail_diag: lda #2 jmp @fail @fail_gen: lda #3 @fail: sta MB_CODE lda #$00 sta MB_CODE+1 lda #MB_ST_FAIL sta MB_STATUS @done: jsr mmu_shutdown plp rts ; Write HELLO.PRG through output.s. C=1 on any output error. emit_hello: lda #name_hello ldy #name_hello_len jsr out_begin ON_CARRY @abort lda #PRG_LOAD_ADDR sta out_start+1 lda #sec_stub ldy #4 jsr out_section ON_CARRY @abort lda #gen_stub ldy #PRG_STUB_SIZE jsr out_bytes ON_CARRY @abort jsr out_end_section ON_CARRY @abort lda #PRG_ENTRY_ADDR sta out_start+1 lda #sec_code ldy #4 jsr out_section ON_CARRY @abort lda #prologue ldy #prologue_len jsr out_bytes ON_CARRY @abort ldy #$00 @chars: cpy gen_text_len beq @epilogue sty temp_y lda #$A9 ; LDA #char jsr out_byte ON_CARRY @abort ldy temp_y lda gen_text,y jsr out_byte ON_CARRY @abort lda #$20 ; JSR $FFD2 (CHROUT) jsr out_byte ON_CARRY @abort lda #$D2 jsr out_byte ON_CARRY @abort lda #$FF jsr out_byte ON_CARRY @abort ldy temp_y iny bne @chars @epilogue: lda #epilogue ldy #epilogue_len jsr out_bytes ON_CARRY @abort jsr out_end_section ON_CARRY @abort jsr out_finish ON_CARRY @abort clc rts @abort: lda out_err sta emit_err jsr out_abort sec rts .segment "RODATA" name_src: .byte "HELLO.N8" name_src_len = * - name_src name_hello: .byte "HELLO" name_hello_len = * - name_hello sec_stub: .byte "STUB" sec_code: .byte "CODE" ; LDA MMU_CR / PHA / LDA #$0E / STA MMU_CR prologue: .byte $AD, $00, $FF, $48, $A9, $0E, $8D, $00, $FF prologue_len = * - prologue ; PLA / STA MMU_CR / RTS epilogue: .byte $68, $8D, $00, $FF, $60 epilogue_len = * - epilogue .segment "BSS" diag_count: .res 1 temp_y: .res 1 emit_err: .res 1