Release 0.95: Added experimental type checking system (still missing docs, however). Made warning about old "!for" syntax configurable.

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@34 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2014-06-02 00:47:46 +00:00
parent c8ff626943
commit d152f60acd
43 changed files with 1516 additions and 1219 deletions

View File

@ -1,13 +1,15 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_6502_std_a !eof
lib_6502_std_a = 1
; labels and macros for plain 6502 processor
cpu_nmi = $fffa
cpu_reset = $fffc
cpu_irq = $fffe
!address {
cpu_nmi = $fffa
cpu_reset = $fffc
cpu_irq = $fffe
}
; skip byte
!macro bit8 {

View File

@ -1,21 +1,23 @@
;ACME 0.07
;ACME 0.95
!ifdef Lib_65816_std_a !eof
Lib_65816_std_a = 1
!ifdef lib_65816_std_a !eof
lib_65816_std_a = 1
; Labels and macros for Western Digital's 65c816 processor
cpu_e_cop = $fff4
cpu_e_abort = $fff8
cpu_e_nmi = $fffa
cpu_e_reset = $fffc
cpu_e_irq = $fffe
!address {
cpu_e_cop = $fff4
cpu_e_abort = $fff8
cpu_e_nmi = $fffa
cpu_e_reset = $fffc
cpu_e_irq = $fffe
cpu_n_cop = $fff4
cpu_n_brk = $fff6
cpu_n_abort = $fff8
cpu_n_nmi = $fffa
cpu_n_irq = $fffe
cpu_n_cop = $fff4
cpu_n_brk = $fff6
cpu_n_abort = $fff8
cpu_n_nmi = $fffa
cpu_n_irq = $fffe
}
!macro cpu_emu {; switch to emulation mode
sec
@ -71,10 +73,9 @@ cpu_n_irq = $fffe
!macro inc24 .t {; increase 24-bit counter
inc .t
bne .j; "*" syntax not used here because size of ".t" is unknown
bne +
inc .t + 1
bne .j
bne +
inc .t + 2
.j
+
}

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c128_kernel_a !eof
lib_cbm_c128_kernel_a = 1
@ -6,27 +6,31 @@ lib_cbm_c128_kernel_a = 1
; Taken from the web.
; Sorry, I can't give credit because I don't have the URL anymore.
k_spin_spout = $ff47
k_close_all = $ff4a
k_c64mode = $ff4d
k_dma_call = $ff50
k_boot_call = $ff53
k_phoenix = $ff56
k_lkupla = $ff59
k_lkupsa = $ff5c
k_swapper = $ff5f
k_dlchr = $ff62
k_pfkey = $ff65
k_setbnk = $ff68
k_getcfg = $ff6b
k_jsrfar = $ff6e
k_jmpfar = $ff71
k_indfet = $ff74
k_indsta = $ff77
k_indcmp = $ff7a
k_primm = $ff7d
k_release_number = $ff80
!address {
k_spin_spout = $ff47
k_close_all = $ff4a
k_c64mode = $ff4d
k_dma_call = $ff50
k_boot_call = $ff53
k_phoenix = $ff56
k_lkupla = $ff59
k_lkupsa = $ff5c
k_swapper = $ff5f
k_dlchr = $ff62
k_pfkey = $ff65
k_setbnk = $ff68
k_getcfg = $ff6b
k_jsrfar = $ff6e
k_jmpfar = $ff71
k_indfet = $ff74
k_indsta = $ff77
k_indcmp = $ff7a
k_primm = $ff7d
k_release_number = $ff80
}
!source <cbm/kernel.a> ; $ff81-$fff5 is backward compatible to older machines
; $fff6/$fff7 are unused (ff ff)
k_indirect128mode = $fff8 ; indirect vector, without JMP command!
!address {
k_indirect128mode = $fff8 ; indirect vector, without JMP command!
}
; $fffa through $ffff are cpu hardware vectors (see <6502/std.a>)

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c128_mmu_a !eof
lib_cbm_c128_mmu_a = 1
@ -8,138 +8,151 @@ lib_cbm_c128_mmu_a = 1
; registers in i/o area (i/o needs to be enabled to access these):
; configuration register
mmu_cr_d500 = $d500 ; same as "mmu_cr" at $ff00. Use "mmu_cr" instead, as that is *always* available.
; preconfiguration registers (internal format just like mmu_cr)
mmu_pcr_a = $d501 ; c128 kernel default is $3f (BANK 0)
mmu_pcr_b = $d502 ; c128 kernel default is $7f (BANK 1)
mmu_pcr_c = $d503 ; c128 kernel default is $01 (BANK 14)
mmu_pcr_d = $d504 ; c128 kernel default is $41 (all system roms, with ram 1)
; contents of cr and all four pcr:
mmu_CR_RAMBANK_MASK = %##...... ; this controls which RAM bank is used in areas where RAM is enabled
; mmu_CR_RAMBANK_0 = %........
mmu_CR_RAMBANK_1 = %.#......
mmu_CR_RAMBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_CR_RAMBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
!address {
; configuration register
mmu_cr_d500 = $d500 ; same as "mmu_cr" at $ff00. Use "mmu_cr" instead, as that is *always* available.
; preconfiguration registers (internal format just like mmu_cr)
mmu_pcr_a = $d501 ; c128 kernel default is $3f (BANK 0)
mmu_pcr_b = $d502 ; c128 kernel default is $7f (BANK 1)
mmu_pcr_c = $d503 ; c128 kernel default is $01 (BANK 14)
mmu_pcr_d = $d504 ; c128 kernel default is $41 (all system roms, with ram 1)
}
; contents of cr and all four pcr:
mmu_CR_RAMBANK_MASK = %##...... ; this controls which RAM bank is used in areas where RAM is enabled
;mmu_CR_RAMBANK_0 = %........
mmu_CR_RAMBANK_1 = %.#......
mmu_CR_RAMBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_CR_RAMBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
mmu_CR_HIGH_MASK = %..##.... ; this controls the "high area" (c000..ffff), but i/o (d000..dfff) is separate
; mmu_CR_HIGH_SYSROM = %........ ; editor, charset (or i/o, see below), kernel
mmu_CR_HIGH_INTFUNCROM = %...#....
mmu_CR_HIGH_EXTFUNCROM = %..#.....
mmu_CR_HIGH_RAM = %..##....
mmu_CR_HIGH_MASK = %..##.... ; this controls the "high area" (c000..ffff), but i/o (d000..dfff) is separate
;mmu_CR_HIGH_SYSROM = %........ ; editor, charset (or i/o, see below), kernel
mmu_CR_HIGH_INTFUNCROM = %...#....
mmu_CR_HIGH_EXTFUNCROM = %..#.....
mmu_CR_HIGH_RAM = %..##....
mmu_CR_MID_MASK = %....##.. ; this controls the "middle area" (8000..bfff)
; mmu_CR_MID_SYSROM = %........ ; this is the upper half of basic
mmu_CR_MID_INTFUNCROM = %.....#..
mmu_CR_MID_EXTFUNCROM = %....#...
mmu_CR_MID_RAM = %....##..
mmu_CR_MID_MASK = %....##.. ; this controls the "middle area" (8000..bfff)
;mmu_CR_MID_SYSROM = %........ ; this is the upper half of basic
mmu_CR_MID_INTFUNCROM = %.....#..
mmu_CR_MID_EXTFUNCROM = %....#...
mmu_CR_MID_RAM = %....##..
mmu_CR_LOW_MASK = %......#. ; this controls the "low area" (4000..7fff)
; mmu_CR_LOW_SYSROM = %........ ; this is the lower half of basic
mmu_CR_LOW_RAM = %......#.
mmu_CR_LOW_MASK = %......#. ; this controls the "low area" (4000..7fff)
;mmu_CR_LOW_SYSROM = %........ ; this is the lower half of basic
mmu_CR_LOW_RAM = %......#.
mmu_CR_IO_MASK = %.......# ; this controls i/o space (d000..dfff)
; mmu_CR_IO_ON = %........
mmu_CR_IO_OFF = %.......# ; if i/o is off, contents depend on "high area"
mmu_CR_IO_MASK = %.......# ; this controls i/o space (d000..dfff)
;mmu_CR_IO_ON = %........
mmu_CR_IO_OFF = %.......# ; if i/o is off, contents depend on "high area"
; configuration register values used by C128 firmware (lookup table at $f7f0, see end of file):
mmu_CR_BANK0 = $3f ; full 64 KiB ram bank 0
mmu_CR_BANK1 = $7f ; full 64 KiB ram bank 1
mmu_CR_BANK2 = $bf ; full 64 KiB ram bank 2
mmu_CR_BANK3 = $ff ; full 64 KiB ram bank 3
mmu_CR_BANK4 = $16 ; 32 KiB bank 0; 32 KiB IFROM with i/o overlay
mmu_CR_BANK5 = $56 ; 32 KiB bank 1; 32 KiB IFROM with i/o overlay
mmu_CR_BANK6 = $96 ; 32 KiB bank 2; 32 KiB IFROM with i/o overlay
mmu_CR_BANK7 = $d6 ; 32 KiB bank 3; 32 KiB IFROM with i/o overlay
mmu_CR_BANK8 = $2a ; 32 KiB bank 0; 32 KiB EFROM with i/o overlay
mmu_CR_BANK9 = $6a ; 32 KiB bank 1; 32 KiB EFROM with i/o overlay
mmu_CR_BANK10 = $aa ; 32 KiB bank 2; 32 KiB EFROM with i/o overlay
mmu_CR_BANK11 = $ea ; 32 KiB bank 3; 32 KiB EFROM with i/o overlay
mmu_CR_BANK12 = $06 ; 32 KiB bank 0; 16 KiB IFROM; 16 KiB kernel with i/o overlay
mmu_CR_BANK13 = $0a ; 32 KiB bank 0; 16 KiB EFROM; 16 KiB kernel with i/o overlay
mmu_CR_BANK14 = $01 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with font overlay
mmu_CR_BANK15 = $00 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with i/o overlay
; An unmodified C128 does not have a "ram bank 2" or "ram bank 3".
; Whenever one of these is activated, ram banks 0 and 1 will be used instead.
; IFROM means internal function ROM (socket U36)
; EFROM means external function ROM (socket in a REU, for example)
; configuration register values used by C128 firmware (lookup table at $f7f0, see end of file):
mmu_CR_BANK0 = $3f ; full 64 KiB ram bank 0
mmu_CR_BANK1 = $7f ; full 64 KiB ram bank 1
mmu_CR_BANK2 = $bf ; full 64 KiB ram bank 2
mmu_CR_BANK3 = $ff ; full 64 KiB ram bank 3
mmu_CR_BANK4 = $16 ; 32 KiB bank 0; 32 KiB IFROM with i/o overlay
mmu_CR_BANK5 = $56 ; 32 KiB bank 1; 32 KiB IFROM with i/o overlay
mmu_CR_BANK6 = $96 ; 32 KiB bank 2; 32 KiB IFROM with i/o overlay
mmu_CR_BANK7 = $d6 ; 32 KiB bank 3; 32 KiB IFROM with i/o overlay
mmu_CR_BANK8 = $2a ; 32 KiB bank 0; 32 KiB EFROM with i/o overlay
mmu_CR_BANK9 = $6a ; 32 KiB bank 1; 32 KiB EFROM with i/o overlay
mmu_CR_BANK10 = $aa ; 32 KiB bank 2; 32 KiB EFROM with i/o overlay
mmu_CR_BANK11 = $ea ; 32 KiB bank 3; 32 KiB EFROM with i/o overlay
mmu_CR_BANK12 = $06 ; 32 KiB bank 0; 16 KiB IFROM; 16 KiB kernel with i/o overlay
mmu_CR_BANK13 = $0a ; 32 KiB bank 0; 16 KiB EFROM; 16 KiB kernel with i/o overlay
mmu_CR_BANK14 = $01 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with font overlay
mmu_CR_BANK15 = $00 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with i/o overlay
; An unmodified C128 does not have a "ram bank 2" or "ram bank 3".
; Whenever one of these is activated, ram banks 0 and 1 will be used instead.
; IFROM means internal function ROM (socket U36)
; EFROM means external function ROM (socket in a REU, for example)
; mode configuration register
mmu_mcr = $d505
; contents:
mmu_MCR_40COLUMNS = %#....... ; 40/80 key: 0 means pressed, 1 means released (writable! if cleared, will always read as 0!)
mmu_MCR_C64MODE = %.#...... ; setting this bit makes the MMU disappear from the memory map :)
mmu_MCR_EXROM = %..#..... ; if zero on boot, system will enter c64 mode (writable!)
mmu_MCR_GAME = %...#.... ; if zero on boot, system will enter c64 mode (writable!)
mmu_MCR_FSDIR_OUTPUT = %....#... ; direction of fast serial bus
mmu_MCR_UNUSED = %.....##. ; always set
mmu_MCR_8502MODE = %.......# ; setting this to zero switches to Z80 cpu
!address {
; mode configuration register
mmu_mcr = $d505
}
; contents:
mmu_MCR_40COLUMNS = %#....... ; 40/80 key: 0 means pressed, 1 means released (writable! if cleared, will always read as 0!)
mmu_MCR_C64MODE = %.#...... ; setting this bit makes the MMU disappear from the memory map :)
mmu_MCR_EXROM = %..#..... ; if zero on boot, system will enter c64 mode (writable!)
mmu_MCR_GAME = %...#.... ; if zero on boot, system will enter c64 mode (writable!)
mmu_MCR_FSDIR_OUTPUT = %....#... ; direction of fast serial bus
mmu_MCR_UNUSED = %.....##. ; always set
mmu_MCR_8502MODE = %.......# ; setting this to zero switches to Z80 cpu
; ram configuration register
mmu_rcr = $d506
; contents:
mmu_RCR_VICBANK_MASK = %##...... ; this controls which RAM bank is "seen" by VIC
; mmu_RCR_VICBANK_0 = %........
mmu_RCR_VICBANK_1 = %.#......
mmu_RCR_VICBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_RCR_VICBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
!address {
; ram configuration register
mmu_rcr = $d506
}
; contents:
mmu_RCR_VICBANK_MASK = %##...... ; this controls which RAM bank is "seen" by VIC
;mmu_RCR_VICBANK_0 = %........
mmu_RCR_VICBANK_1 = %.#......
mmu_RCR_VICBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_RCR_VICBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
mmu_RCR_RAMBLOCK_MASK = %..##.... ; on an unmodified c128, these bits are irrelevant (they select 256 KiB of 1 MiB of memory)
; mmu_RCR_RAMBLOCK_0 = %........
mmu_RCR_RAMBLOCK_1 = %...#.... ; on an unmodified c128, there is only ram block 0
mmu_RCR_RAMBLOCK_2 = %..#..... ; on an unmodified c128, there is only ram block 0
mmu_RCR_RAMBLOCK_3 = %..##.... ; on an unmodified c128, there is only ram block 0
mmu_RCR_RAMBLOCK_MASK = %..##.... ; on an unmodified c128, these bits are irrelevant (they select 256 KiB of 1 MiB of memory)
;mmu_RCR_RAMBLOCK_0 = %........
mmu_RCR_RAMBLOCK_1 = %...#.... ; on an unmodified c128, there is only ram block 0
mmu_RCR_RAMBLOCK_2 = %..#..... ; on an unmodified c128, there is only ram block 0
mmu_RCR_RAMBLOCK_3 = %..##.... ; on an unmodified c128, there is only ram block 0
mmu_RCR_SHARE_MASK = %....##..
; mmu_RCR_SHARE_NONE = %........
mmu_RCR_SHARE_BOTTOM = %.....#.. ; system default
mmu_RCR_SHARE_TOP = %....#...
mmu_RCR_SHARE_MASK = %....##..
;mmu_RCR_SHARE_NONE = %........
mmu_RCR_SHARE_BOTTOM = %.....#.. ; system default
mmu_RCR_SHARE_TOP = %....#...
mmu_RCR_SHARESIZE_MASK = %......##
; mmu_RCR_SHARESIZE_1K = %........ ; system default
mmu_RCR_SHARESIZE_4K = %.......#
mmu_RCR_SHARESIZE_8K = %......#.
mmu_RCR_SHARESIZE_16K = %......##
mmu_RCR_SHARESIZE_MASK = %......##
;mmu_RCR_SHARESIZE_1K = %........ ; system default
mmu_RCR_SHARESIZE_4K = %.......#
mmu_RCR_SHARESIZE_8K = %......#.
mmu_RCR_SHARESIZE_16K = %......##
; page pointers. writes to "high" register will be latched (reading gives old value) until "low" register is written to
mmu_p0low = $d507 ; page 0 pointer low (a8..a15), default $00
mmu_p0high = $d508 ; page 0 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful)
mmu_p1low = $d509 ; page 1 pointer low (a8..a15), default $01
mmu_p1high = $d50a ; page 1 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful)
mmu_PxH_UNUSED = %####.... ; always set
!address {
; page pointers. writes to "high" register will be latched (reading gives old value) until "low" register is written to
mmu_p0low = $d507 ; page 0 pointer low (a8..a15), default $00
mmu_p0high = $d508 ; page 0 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful)
mmu_p1low = $d509 ; page 1 pointer low (a8..a15), default $01
mmu_p1high = $d50a ; page 1 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful)
}
mmu_PxH_UNUSED = %####.... ; always set
mmu_PxH_RAMBLOCK_MASK = %....##..
; mmu_PxH_RAMBLOCK_0 = %........
mmu_PxH_RAMBLOCK_1 = %.....#.. ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBLOCK_2 = %....#... ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBLOCK_3 = %....##.. ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBLOCK_MASK = %....##..
;mmu_PxH_RAMBLOCK_0 = %........
mmu_PxH_RAMBLOCK_1 = %.....#.. ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBLOCK_2 = %....#... ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBLOCK_3 = %....##.. ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBANK_MASK = %......##
; mmu_PxH_RAMBANK_0 = %........
mmu_PxH_RAMBANK_1 = %.......#
mmu_PxH_RAMBANK_2 = %......#. ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_PxH_RAMBANK_3 = %......## ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
mmu_PxH_RAMBANK_MASK = %......##
;mmu_PxH_RAMBANK_0 = %........
mmu_PxH_RAMBANK_1 = %.......#
mmu_PxH_RAMBANK_2 = %......#. ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_PxH_RAMBANK_3 = %......## ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
!address {
; version register
mmu_vr = $d50b ; read-only, value is $20
}
mmu_VR_BANKS_MASK = %####.... ; 2 ram banks
mmu_VR_VERSION_MASK = %....#### ; mmu version 0
; version register
mmu_vr = $d50b ; read-only, value is $20
mmu_VR_BANKS_MASK = %####.... ; 2 ram banks
mmu_VR_VERSION_MASK = %....#### ; mmu version 0
; reading addresses up until $d5ff returns $ff
; these registers are always available (in *every* memory configuration) unless C64 mode is entered:
; configuration register
mmu_cr = $ff00 ; always use this instead of $d500
; load configuration registers:
; a read access will return the value of the corresponding preconfiguration register
; any write access will copy the value of the corresponding preconfiguration register to mmu_cr
mmu_lcr_a = $ff01 ; c128 kernel default is $3f (BANK 0)
mmu_lcr_b = $ff02 ; c128 kernel default is $7f (BANK 1)
mmu_lcr_c = $ff03 ; c128 kernel default is $01 (BANK 14)
mmu_lcr_d = $ff04 ; c128 kernel default is $41 (all system roms, with ram 1)
!address {
; configuration register
mmu_cr = $ff00 ; always use this instead of $d500
; load configuration registers:
; a read access will return the value of the corresponding preconfiguration register
; any write access will copy the value of the corresponding preconfiguration register to mmu_cr
mmu_lcr_a = $ff01 ; c128 kernel default is $3f (BANK 0)
mmu_lcr_b = $ff02 ; c128 kernel default is $7f (BANK 1)
mmu_lcr_c = $ff03 ; c128 kernel default is $01 (BANK 14)
mmu_lcr_d = $ff04 ; c128 kernel default is $41 (all system roms, with ram 1)
; the c128 ROMs contain a look-up table to convert bank numbers to their
; corresponding configuration register values:
; romc_* needs "high rom area" enabled ($c000..$ffff)
romc_bank_to_cr_table = $f7f0 ; 3f 7f bf ff 16 56 96 d6 2a 6a aa ea 06 0a 01 00
; the c128 ROMs contain a look-up table to convert bank numbers to their
; corresponding configuration register values:
; romc_* needs "high rom area" enabled ($c000..$ffff)
romc_bank_to_cr_table = $f7f0 ; 3f 7f bf ff 16 56 96 d6 2a 6a aa ea 06 0a 01 00
}

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c128_vdc_a !eof
lib_cbm_c128_vdc_a = 1
@ -135,14 +135,17 @@ vdcattr_B = %......#. ; blue
vdcattr_I = %.......# ; intensity
; direct registers
vdc_state = $d600 ; READING this location yields status flags:
vdcstate_READY = %#....... ; RAM access is finished
vdcstate_LIGHTPEN = %.#...... ; light pen has been activated
vdcstate_IN_BORDER = %..#..... ; electron beam is in upper or lower border
vdcstate_VERSIONMASK = %...##### ; vdc version (0, 1 or 2)
vdc_reg = $d600 ; WRITING this location selects an indirect register
vdc_data = $d601 ; data of selected indirect register
!address {
; direct registers
vdc_state = $d600 ; READING this location yields status flags, see below
vdc_reg = $d600 ; WRITING this location selects an indirect register
vdc_data = $d601 ; data of selected indirect register
}
; status flags in vdc_state:
vdcstate_READY = %#....... ; RAM access is finished
vdcstate_LIGHTPEN = %.#...... ; light pen has been activated
vdcstate_IN_BORDER = %..#..... ; electron beam is in upper or lower border
vdcstate_VERSIONMASK = %...##### ; vdc version (0, 1 or 2)
; indirect registers (default value, see $e179 in C128 kernal)
@ -219,11 +222,13 @@ vdcr_sync_polarity = $25 ; -- only in VDC 8568
vdcr_HSYNC_POLARITY = %#.......
vdcr_VSYNC_POLARITY = %.#......
; the c128 ROMs contain look-up tables to convert vic color values to vdc color
; values and vice-versa:
; rom4_* needs "low rom area" enabled ($4000..$7fff)
; rom8_* needs "middle rom area" enabled ($8000..$bfff)
; romc_* needs "high rom area" enabled ($c000..$ffff)
rom4_vic_to_vdc_color_table = $6a4c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e
rom8_vdc_to_vic_color_table = $81f3 ; 00 0c 06 0e 05 0d 0b 03 02 0a 08 04 09 07 0f 01
romc_vic_to_vdc_color_table = $ce5c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e
!address {
; the c128 ROMs contain look-up tables to convert vic color values to vdc color
; values and vice-versa:
; rom4_* needs "low rom area" enabled ($4000..$7fff)
; rom8_* needs "middle rom area" enabled ($8000..$bfff)
; romc_* needs "high rom area" enabled ($c000..$ffff)
rom4_vic_to_vdc_color_table = $6a4c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e
rom8_vdc_to_vic_color_table = $81f3 ; 00 0c 06 0e 05 0d 0b 03 02 0a 08 04 09 07 0f 01
romc_vic_to_vdc_color_table = $ce5c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e
}

View File

@ -1,17 +1,19 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c128_vic_a !eof
lib_cbm_c128_vic_a = 1
!source <cbm/c64/vic.a> ; registers 0..2e
; registers only present in the C128 variant of this chip:
vic_keyboard = $d02f
vic_clock = $d030
!address {
; registers only present in the C128 variant of this chip:
vic_keyboard = $d02f
vic_clock = $d030
; the c128 ROMs contain two copies of a look-up table to convert vic color
; values to their corresponding petscii color codes:
; rom4_* needs "low rom area" enabled ($4000..$7fff)
; romc_* needs "high rom area" enabled ($c000..$ffff)
rom4_vic_to_petscii_color_table = $76b5 ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b
romc_vic_to_petscii_color_table = $ce4c ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b
; the c128 ROMs contain two copies of a look-up table to convert vic color
; values to their corresponding petscii color codes:
; rom4_* needs "low rom area" enabled ($4000..$7fff)
; romc_* needs "high rom area" enabled ($c000..$ffff)
rom4_vic_to_petscii_color_table = $76b5 ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b
romc_vic_to_petscii_color_table = $ce4c ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b
}

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,23 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c64_cia1_a !eof
lib_cbm_c64_cia1_a = 1
cia1_pra = $dc00
cia1_prb = $dc01
cia1_ddra = $dc02
cia1_ddrb = $dc03
cia1_ta_lo = $dc04
cia1_ta_hi = $dc05
cia1_tb_lo = $dc06
cia1_tb_hi = $dc07
cia1_tod10ths = $dc08
cia1_todsec = $dc09
cia1_todmin = $dc0a
cia1_todhr = $dc0b
cia1_sdr = $dc0c
cia1_icr = $dc0d
cia1_cra = $dc0e
cia1_crb = $dc0f
!address {
cia1_pra = $dc00
cia1_prb = $dc01
cia1_ddra = $dc02
cia1_ddrb = $dc03
cia1_ta_lo = $dc04
cia1_ta_hi = $dc05
cia1_tb_lo = $dc06
cia1_tb_hi = $dc07
cia1_tod10ths = $dc08
cia1_todsec = $dc09
cia1_todmin = $dc0a
cia1_todhr = $dc0b
cia1_sdr = $dc0c
cia1_icr = $dc0d
cia1_cra = $dc0e
cia1_crb = $dc0f
}

View File

@ -1,21 +1,23 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c64_cia2_a !eof
lib_cbm_c64_cia2_a = 1
cia2_pra = $dd00
cia2_prb = $dd01
cia2_ddra = $dd02
cia2_ddrb = $dd03
cia2_ta_lo = $dd04
cia2_ta_hi = $dd05
cia2_tb_lo = $dd06
cia2_tb_hi = $dd07
cia2_tod10ths = $dd08
cia2_todsec = $dd09
cia2_todmin = $dd0a
cia2_todhr = $dd0b
cia2_sdr = $dd0c
cia2_icr = $dd0d
cia2_cra = $dd0e
cia2_crb = $dd0f
!address {
cia2_pra = $dd00
cia2_prb = $dd01
cia2_ddra = $dd02
cia2_ddrb = $dd03
cia2_ta_lo = $dd04
cia2_ta_hi = $dd05
cia2_tb_lo = $dd06
cia2_tb_hi = $dd07
cia2_tod10ths = $dd08
cia2_todsec = $dd09
cia2_todmin = $dd0a
cia2_todhr = $dd0b
cia2_sdr = $dd0c
cia2_icr = $dd0d
cia2_cra = $dd0e
cia2_crb = $dd0f
}

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c64_float_a !eof
lib_cbm_c64_float_a = 1
@ -6,8 +6,10 @@ lib_cbm_c64_float_a = 1
; Here are some definitions to help you call the floating-point functions of the
; C64's BASIC ROM. They work on "float registers", which are actually just
; structures in zero page:
fac1_base = $61 ; base address of floating-point accumulator 1
fac2_base = $69 ; base address of floating-point accumulator 2
!address {
fac1_base = $61 ; base address of floating-point accumulator 1
fac2_base = $69 ; base address of floating-point accumulator 2
}
; There is really no need to use these addresses directly when calling the ROM
; functions. You'd only need the addresses when using <cbm/flpt.a>.
@ -45,69 +47,71 @@ fac2_base = $69 ; base address of floating-point accumulator 2
lda .adr + 1
}
; constants in five-byte "mflpt" format
mflpt_pi = $aea8 ; 3.1415926...
mflpt_minus32768 = $b1a5 ; -32768
mflpt_1 = $b9bc ; 1
mflpt_half_sqr2 = $b9d6 ; SQR(2) / 2
mflpt_sqr2 = $b9db ; SQR(2)
mflpt_minus_point5 = $b9e0 ; -.5
mflpt_log_2 = $b9e5 ; LOG(2)
mflpt_10 = $baf9 ; 10
mflpt_99999999 = $bdb3 ; 99 999 999
mflpt_999999999 = $bdb8 ; 999 999 999
mflpt_1000000000 = $bdbd ; 1 000 000 000
mflpt_point5 = $bf11 ; .5, also known as 1 / 2
mflpt_log_2_reciprocal = $bfbf ; 1 / LOG(2)
mflpt_half_pi = $e2e0 ; PI / 2
mflpt_double_pi = $e2e5 ; 2 * PI (also see $e309)
mflpt_point25 = $e2ea ; .25, also known as 1 / 4
mflpt_2_pi = $e309 ; 2 * PI (also see $e2e5)
!address {
; constants in five-byte "mflpt" format
mflpt_pi = $aea8 ; 3.1415926...
mflpt_minus32768 = $b1a5 ; -32768
mflpt_1 = $b9bc ; 1
mflpt_half_sqr2 = $b9d6 ; SQR(2) / 2
mflpt_sqr2 = $b9db ; SQR(2)
mflpt_minus_point5 = $b9e0 ; -.5
mflpt_log_2 = $b9e5 ; LOG(2)
mflpt_10 = $baf9 ; 10
mflpt_99999999 = $bdb3 ; 99 999 999
mflpt_999999999 = $bdb8 ; 999 999 999
mflpt_1000000000 = $bdbd ; 1 000 000 000
mflpt_point5 = $bf11 ; .5, also known as 1 / 2
mflpt_log_2_reciprocal = $bfbf ; 1 / LOG(2)
mflpt_half_pi = $e2e0 ; PI / 2
mflpt_double_pi = $e2e5 ; 2 * PI (also see $e309)
mflpt_point25 = $e2ea ; .25, also known as 1 / 4
mflpt_2_pi = $e309 ; 2 * PI (also see $e2e5)
; functions - a few points to note:
; fac1/2 might get clobbered even if not mentioned in the function's name,
; because stuff like fac1_times_memAY will load the value from memory
; into fac2 first.
; for subtraction and division, the left operand is in fac2, the right operand in fac1.
fac1_print = $aabc ; print string representation of contents of fac1
fac1_to_signedYA = $b1aa ; might throw ILLEGAL QUANTITY
fac1_to_signed16 = $b1bf ; might throw ILLEGAL QUANTITY
fac1_read_signedYA = $b391 ; convert 16 bit signed int to float
fac1_read_unsignedY = $b3a2 ; convert 8 bit unsigned int to float
fac1_read_string = $b7b5 ; $22/23 must point to string, A must be string length
fac1_to_unsignedYA = $b7f7 ; might throw ILLEGAL QUANTITY (result is also in $14/15)
fac1_add_point5 = $b849 ; for rounding, call this before fac1_int
fac1_memAY_minus_fac1 = $b850 ; subtract fac1 from mflpt value
fac1_fac2_minus_fac1 = $b853
fac1_add_memAY = $b867 ; add mflpt value
fac1_add_fac2 = $b86a
fac1_log = $b9ea ; LOG()
fac1_times_memAY = $ba28 ; multiply by mflpt value
fac2_read_memAY = $ba8c ; load mflpt value from memory into fac2
fac2_read_mem_via0x22ptr = $ba90 ; load mflpt value from memory into fac2
fac1_times_10 = $bae2
fac1_divide_by_10 = $bafe
fac1_divide_memAY_by_fac1 = $bb0f ; divide mflpt value by fac1 value
fac1_read_memAY = $bba2 ; load mflpt value from memory into fac1
fac1_read_mem_via0x22ptr = $bba6 ; load mflpt value from memory into fac1
fac1_to_memXY = $bbd4 ; store fac1 to memory as mflpt
fac1_read_fac2 = $bbfc ; copy fac2 to fac1
fac2_read_fac1 = $bc0c ; copy fac1 to fac2
fac1_sign_to_A = $bc2b ; $ff, $0, $1 for negative, zero, positive
fac1_sgn = $bc39 ; SGN()
fac1_abs = $bc58 ; ABS()
fac1_compare_to_memAY = $bc5b ; compare to mflpt value in memory
fac1_to_signed32 = $bc9b
fac1_int = $bccc ; INT()
fac1_print_unsignedXA = $bdcd
fac1_to_string = $bddd ; string is stored at $0100 (address returned in AY)
fac1_sqr = $bf71 ; SQR()
fac1_fac2_to_the_power_of_memAY = $bf78
fac1_negate = $bfb4
fac1_exp = $bfed ; EXP()
; end of basic rom jumps to start of kernel rom!
fac1_rnd = $e097 ; RND()
fac1_cos = $e264 ; COS()
fac1_sin = $e26b ; SIN()
fac1_tan = $e2b4 ; TAN()
fac1_atn = $e30e ; ATN()
; functions - a few points to note:
; fac1/2 might get clobbered even if not mentioned in the function's name,
; because stuff like fac1_times_memAY will load the value from memory
; into fac2 first.
; for subtraction and division, the left operand is in fac2, the right operand in fac1.
fac1_print = $aabc ; print string representation of contents of fac1
fac1_to_signedYA = $b1aa ; might throw ILLEGAL QUANTITY
fac1_to_signed16 = $b1bf ; might throw ILLEGAL QUANTITY
fac1_read_signedYA = $b391 ; convert 16 bit signed int to float
fac1_read_unsignedY = $b3a2 ; convert 8 bit unsigned int to float
fac1_read_string = $b7b5 ; $22/23 must point to string, A must be string length
fac1_to_unsignedYA = $b7f7 ; might throw ILLEGAL QUANTITY (result is also in $14/15)
fac1_add_point5 = $b849 ; for rounding, call this before fac1_int
fac1_memAY_minus_fac1 = $b850 ; subtract fac1 from mflpt value
fac1_fac2_minus_fac1 = $b853
fac1_add_memAY = $b867 ; add mflpt value
fac1_add_fac2 = $b86a
fac1_log = $b9ea ; LOG()
fac1_times_memAY = $ba28 ; multiply by mflpt value
fac2_read_memAY = $ba8c ; load mflpt value from memory into fac2
fac2_read_mem_via0x22ptr = $ba90 ; load mflpt value from memory into fac2
fac1_times_10 = $bae2
fac1_divide_by_10 = $bafe
fac1_divide_memAY_by_fac1 = $bb0f ; divide mflpt value by fac1 value
fac1_read_memAY = $bba2 ; load mflpt value from memory into fac1
fac1_read_mem_via0x22ptr = $bba6 ; load mflpt value from memory into fac1
fac1_to_memXY = $bbd4 ; store fac1 to memory as mflpt
fac1_read_fac2 = $bbfc ; copy fac2 to fac1
fac2_read_fac1 = $bc0c ; copy fac1 to fac2
fac1_sign_to_A = $bc2b ; $ff, $0, $1 for negative, zero, positive
fac1_sgn = $bc39 ; SGN()
fac1_abs = $bc58 ; ABS()
fac1_compare_to_memAY = $bc5b ; compare to mflpt value in memory
fac1_to_signed32 = $bc9b
fac1_int = $bccc ; INT()
fac1_print_unsignedXA = $bdcd
fac1_to_string = $bddd ; string is stored at $0100 (address returned in AY)
fac1_sqr = $bf71 ; SQR()
fac1_fac2_to_the_power_of_memAY = $bf78
fac1_negate = $bfb4
fac1_exp = $bfed ; EXP()
; end of basic rom jumps to start of kernel rom!
fac1_rnd = $e097 ; RND()
fac1_cos = $e264 ; COS()
fac1_sin = $e26b ; SIN()
fac1_tan = $e2b4 ; TAN()
fac1_atn = $e30e ; ATN()
}

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c64_georam_a !eof
lib_cbm_c64_georam_a = 1
@ -9,12 +9,13 @@ lib_cbm_c64_georam_a = 1
; address $de00 in i/o space. Writing to registers allows to change which
; memory page is visible at that location.
; memory page
georam_page = $de00
; control registers (write-only, these registers can not be read)
georam_track = $dffe ; 0..63, i.e. the lower six bits are significant
georam_sector = $dfff ; 0..31, i.e. the lower five bits are significant
!address {
; memory page
georam_page = $de00
; control registers (write-only, these registers can not be read)
georam_track = $dffe ; 0..63, i.e. the lower six bits are significant
georam_sector = $dfff ; 0..31, i.e. the lower five bits are significant
}
; these are the official addresses - actually the registers are accessible
; *everywhere* at $dfxx, but using these locations does not clash with the
; registers of a Commodore REU.

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c64_reu_a !eof
lib_cbm_c64_reu_a = 1
@ -8,48 +8,56 @@ lib_cbm_c64_reu_a = 1
; (RAM Expansion Controller) capable of direct memory access (DMA).
; Standard base address of control registers is $df00 in i/o space.
; status register
rec_status = $df00 ; reading will clear IRQ, END and ERROR bits
rec_STATUS_IRQ = %#.......
rec_STATUS_END = %.#......
rec_STATUS_ERROR = %..#..... ; for verify command
rec_STATUS_TYPE = %...#.... ; chip type (do not use to determine unit size!)
rec_STATUS_VERSION = %....####
; command register
rec_command = $df01
rec_COMMAND_EXECUTE = %#.......
;reserved = %.#......
rec_COMMAND_RELOAD = %..#.....
rec_COMMAND_IMMEDIATELY = %...#.... ; do not wait for $ff00 write
;reserved = %....##..
rec_COMMAND_MODE_MASK = %......## ; bit mask for the four modes
rec_COMMAND_MODE_STASH = %........ ; computer-to-REU
rec_COMMAND_MODE_FETCH = %.......# ; REU-to-computer
rec_COMMAND_MODE_SWAP = %......#. ; exchange
rec_COMMAND_MODE_VERIFY = %......## ; compare
rec_COMMAND_STASH = %#.#..... ; these wait for $ff00 before
rec_COMMAND_FETCH = %#.#....# ; starting and then reload values.
; internal address (computer RAM)
rec_int_low = $df02
rec_int_high = $df03
; external address (expansion RAM)
rec_ext_low = $df04
rec_ext_high = $df05
rec_ext_bank = $df06
!address {
; status register
rec_status = $df00 ; reading will clear IRQ, END and ERROR bits
}
rec_STATUS_IRQ = %#.......
rec_STATUS_END = %.#......
rec_STATUS_ERROR = %..#..... ; for verify command
rec_STATUS_TYPE = %...#.... ; chip type (do not use to determine unit size!)
rec_STATUS_VERSION = %....####
!address {
; command register
rec_command = $df01
}
rec_COMMAND_EXECUTE = %#.......
;reserved = %.#......
rec_COMMAND_RELOAD = %..#.....
rec_COMMAND_IMMEDIATELY = %...#.... ; do not wait for $ff00 write
;reserved = %....##..
rec_COMMAND_MODE_MASK = %......## ; bit mask for the four modes
rec_COMMAND_MODE_STASH = %........ ; computer-to-REU
rec_COMMAND_MODE_FETCH = %.......# ; REU-to-computer
rec_COMMAND_MODE_SWAP = %......#. ; exchange
rec_COMMAND_MODE_VERIFY = %......## ; compare
rec_COMMAND_STASH = %#.#..... ; these wait for $ff00 before
rec_COMMAND_FETCH = %#.#....# ; starting and then reload values.
!address {
; internal address (computer RAM)
rec_int_low = $df02
rec_int_high = $df03
; external address (expansion RAM)
rec_ext_low = $df04
rec_ext_high = $df05
rec_ext_bank = $df06
; A stock 1700 unit has two banks (128 KiB).
; A stock 1764 unit has four banks (256 KiB).
; A stock 1750 unit has eight banks (512 KiB).
; Upgraded units and clones may have more, but the REC chip will always
; "wrap around" after eight banks if crossing bank borders!
; amount of bytes to process
rec_amount_low = $df07
rec_amount_high = $df08
; when to request interrupts
rec_irqctrl = $df09
rec_IRQCTRL_ENABLE = %#.......
rec_IRQCTRL_ON_END = %.#......
rec_IRQCTRL_ON_ERROR = %..#..... ; for verify errors
; address control (set to zero for normal operation)
rec_addrctrl = $df0a
rec_ADDRCTRL_FIX_INT = %#.......
rec_ADDRCTRL_FIX_EXT = %.#......
; amount of bytes to process
rec_amount_low = $df07
rec_amount_high = $df08
; when to request interrupts
rec_irqctrl = $df09
}
rec_IRQCTRL_ENABLE = %#.......
rec_IRQCTRL_ON_END = %.#......
rec_IRQCTRL_ON_ERROR = %..#..... ; for verify errors
!address {
; address control (set to zero for normal operation)
rec_addrctrl = $df0a
}
rec_ADDRCTRL_FIX_INT = %#.......
rec_ADDRCTRL_FIX_EXT = %.#......

View File

@ -1,52 +1,55 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c64_sid_a !eof
lib_cbm_c64_sid_a = 1
; write-only registers:
; voice 1:
sid_v1_freq_lo = $d400
sid_v1_freq_hi = $d401
sid_v1_width_lo = $d402
sid_v1_width_hi = $d403
sid_v1_control = $d404 ; see below for bits
sid_v1_attack_decay = $d405 ; hi-nibble: attack length, low-nibble: decay length
sid_v1_sustain_release = $d406 ; hi-nibble: sustain volumne, low-nibble: release length
; voice 2:
sid_v2_freq_lo = $d407
sid_v2_freq_hi = $d408
sid_v2_width_lo = $d409
sid_v2_width_hi = $d40a
sid_v2_control = $d40b ; see below for bits
sid_v2_attack_decay = $d40c ; hi-nibble: attack length, low-nibble: decay length
sid_v2_sustain_release = $d40d ; hi-nibble: sustain volumne, low-nibble: release length
; voice 3:
sid_v3_freq_lo = $d40e
sid_v3_freq_hi = $d40f
sid_v3_width_lo = $d410
sid_v3_width_hi = $d411
sid_v3_control = $d412 ; see below for bits
sid_v3_attack_decay = $d413 ; hi-nibble: attack length, low-nibble: decay length
sid_v3_sustain_release = $d414 ; hi-nibble: sustain volumne, low-nibble: release length
!address {
; write-only registers:
; voice 1:
sid_v1_freq_lo = $d400
sid_v1_freq_hi = $d401
sid_v1_width_lo = $d402
sid_v1_width_hi = $d403
sid_v1_control = $d404 ; see below for bits
sid_v1_attack_decay = $d405 ; hi-nibble: attack length, low-nibble: decay length
sid_v1_sustain_release = $d406 ; hi-nibble: sustain volumne, low-nibble: release length
; voice 2:
sid_v2_freq_lo = $d407
sid_v2_freq_hi = $d408
sid_v2_width_lo = $d409
sid_v2_width_hi = $d40a
sid_v2_control = $d40b ; see below for bits
sid_v2_attack_decay = $d40c ; hi-nibble: attack length, low-nibble: decay length
sid_v2_sustain_release = $d40d ; hi-nibble: sustain volumne, low-nibble: release length
; voice 3:
sid_v3_freq_lo = $d40e
sid_v3_freq_hi = $d40f
sid_v3_width_lo = $d410
sid_v3_width_hi = $d411
sid_v3_control = $d412 ; see below for bits
sid_v3_attack_decay = $d413 ; hi-nibble: attack length, low-nibble: decay length
sid_v3_sustain_release = $d414 ; hi-nibble: sustain volumne, low-nibble: release length
}
; voice control bits:
sid_VOICECONTROL_NOISE = %#.......
sid_VOICECONTROL_RECTANGLE = %.#......
sid_VOICECONTROL_SAWTOOTH = %..#.....
sid_VOICECONTROL_TRIANGLE = %...#....
sid_VOICECONTROL_DISABLE_RESET = %....#... ; 1 = disable voice, reset noise generator
sid_VOICECONTROL_RINGMODULATION = %.....#..
sid_VOICECONTROL_SYNC = %......#.
sid_VOICECONTROL_ON = %.......# ; 0 = release, 1 = attack/sustain/decay
; registers shared by all voices:
sid_filter_cutoff_lo = $d415 ; only bits 0/1/2!
sid_filter_cutoff_hi = $d416
sid_filter_control = $d417 ; hi-nibble: resonance, lo-nibble: filter ext/v3/v2/v1
sid_filter_volume = $d418 ; hi-nibble: filter mode (disable v3, high, band, low), lo-nibble: volume
; read-only registers:
sid_potx = $d419
sid_poty = $d41a
sid_v3_waveform_output = $d41b
sid_v3_adsr_output = $d41c
; Do not use the shadow copies of these registers at $d500, $d600 or $d700,
sid_VOICECONTROL_NOISE = %#.......
sid_VOICECONTROL_RECTANGLE = %.#......
sid_VOICECONTROL_SAWTOOTH = %..#.....
sid_VOICECONTROL_TRIANGLE = %...#....
sid_VOICECONTROL_DISABLE_RESET = %....#... ; 1 = disable voice, reset noise generator
sid_VOICECONTROL_RINGMODULATION = %.....#..
sid_VOICECONTROL_SYNC = %......#.
sid_VOICECONTROL_ON = %.......# ; 0 = release, 1 = attack/sustain/decay
!address {
; registers shared by all voices:
sid_filter_cutoff_lo = $d415 ; only bits 0/1/2!
sid_filter_cutoff_hi = $d416
sid_filter_control = $d417 ; hi-nibble: resonance, lo-nibble: filter ext/v3/v2/v1
sid_filter_volume = $d418 ; hi-nibble: filter mode (disable v3, high, band, low), lo-nibble: volume
; read-only registers:
sid_potx = $d419
sid_poty = $d41a
sid_v3_waveform_output = $d41b
sid_v3_adsr_output = $d41c
}
; Do not use the shadow copies of these registers at $d5xx, $d6xx or $d7xx:
; on a C128 they do not exist!

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_c64_vic_a !eof
lib_cbm_c64_vic_a = 1
@ -21,58 +21,58 @@ viccolor_LGREEN = $d
viccolor_LBLUE = $e
viccolor_GRAY3 = $f
; register addresses
vic_xs0 = $d000
vic_ys0 = $d001
vic_xs1 = $d002
vic_ys1 = $d003
vic_xs2 = $d004
vic_ys2 = $d005
vic_xs3 = $d006
vic_ys3 = $d007
vic_xs4 = $d008
vic_ys4 = $d009
vic_xs5 = $d00a
vic_ys5 = $d00b
vic_xs6 = $d00c
vic_ys6 = $d00d
vic_xs7 = $d00e
vic_ys7 = $d00f
vic_msb_xs = $d010
vic_controlv = $d011 ; vertical control (and much other stuff)
vic_line = $d012 ; raster line
vic_xlp = $d013 ; light pen coordinates
vic_ylp = $d014
vic_sactive = $d015 ; sprites: active
vic_controlh = $d016 ; horizontal control (and much other stuff)
vic_sdy = $d017 ; sprites: double height
vic_ram = $d018 ; RAM pointer
vic_irq = $d019
vic_irqmask = $d01a
vic_sback = $d01b ; sprites: background mode
vic_smc = $d01c ; sprites: multi color mode
vic_sdx = $d01d ; sprites: double width
vic_ss_collided = $d01e ; sprite-sprite collision detect
vic_sd_collided = $d01f ; sprite-data collision detect
; color registers
vic_cborder = $d020 ; border color
vic_cbg = $d021 ; general background color
vic_cbg0 = $d021
vic_cbg1 = $d022 ; background color 1 (for EBC and MC text mode)
vic_cbg2 = $d023 ; background color 2 (for EBC and MC text mode)
vic_cbg3 = $d024 ; background color 3 (for EBC mode)
vic_sc01 = $d025 ; sprite color for MC-bitpattern %01
vic_sc11 = $d026 ; sprite color for MC-bitpattern %11
vic_cs0 = $d027 ; sprite colors
vic_cs1 = $d028
vic_cs2 = $d029
vic_cs3 = $d02a
vic_cs4 = $d02b
vic_cs5 = $d02c
vic_cs6 = $d02d
vic_cs7 = $d02e
!address {
; register addresses
vic_xs0 = $d000
vic_ys0 = $d001
vic_xs1 = $d002
vic_ys1 = $d003
vic_xs2 = $d004
vic_ys2 = $d005
vic_xs3 = $d006
vic_ys3 = $d007
vic_xs4 = $d008
vic_ys4 = $d009
vic_xs5 = $d00a
vic_ys5 = $d00b
vic_xs6 = $d00c
vic_ys6 = $d00d
vic_xs7 = $d00e
vic_ys7 = $d00f
vic_msb_xs = $d010
vic_controlv = $d011 ; vertical control (and much other stuff)
vic_line = $d012 ; raster line
vic_xlp = $d013 ; light pen coordinates
vic_ylp = $d014
vic_sactive = $d015 ; sprites: active
vic_controlh = $d016 ; horizontal control (and much other stuff)
vic_sdy = $d017 ; sprites: double height
vic_ram = $d018 ; RAM pointer
vic_irq = $d019
vic_irqmask = $d01a
vic_sback = $d01b ; sprites: background mode
vic_smc = $d01c ; sprites: multi color mode
vic_sdx = $d01d ; sprites: double width
vic_ss_collided = $d01e ; sprite-sprite collision detect
vic_sd_collided = $d01f ; sprite-data collision detect
; color registers
vic_cborder = $d020 ; border color
vic_cbg = $d021 ; general background color
vic_cbg0 = $d021
vic_cbg1 = $d022 ; background color 1 (for EBC and MC text mode)
vic_cbg2 = $d023 ; background color 2 (for EBC and MC text mode)
vic_cbg3 = $d024 ; background color 3 (for EBC mode)
vic_sc01 = $d025 ; sprite color for MC-bitpattern %01
vic_sc11 = $d026 ; sprite color for MC-bitpattern %11
vic_cs0 = $d027 ; sprite colors
vic_cs1 = $d028
vic_cs2 = $d029
vic_cs3 = $d02a
vic_cs4 = $d02b
vic_cs5 = $d02c
vic_cs6 = $d02d
vic_cs7 = $d02e
}
; See <cbm/c128/vic.a> for the C128's two additional registers at $d02f/$d030.
; They are accessible even in C64 mode and $d030 can garble the video output,
; so be careful not to write to it accidentally in a C64 program!

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!ifdef lib_cbm_kernel_a !eof
lib_cbm_kernel_a = 1
@ -7,42 +7,44 @@ lib_cbm_kernel_a = 1
; Sorry, I can't give credit because I don't have the URL anymore.
; There are alternative names for some calls.
k_cint = $ff81
k_ioinit = $ff84
k_ramtas = $ff87
k_restor = $ff8a
k_vector = $ff8d
k_setmsg = $ff90
k_secnd = $ff93
k_tksa = $ff96
k_memtop = $ff99
k_membot = $ff9c
k_key = $ff9f
k_settmo = $ffa2
k_iecin = $ffa5:k_acptr = $ffa5
k_iecout = $ffa8:k_ciout = $ffa8
k_untalk = $ffab:k_untlk = $ffab
k_unlisten = $ffae:k_unlsn = $ffae
k_listen = $ffb1:k_listn = $ffb1
k_talk = $ffb4
k_readss = $ffb7
k_setlfs = $ffba
k_setnam = $ffbd ; A is length, X is ptr-low, Y is ptr-high
k_open = $ffc0
k_close = $ffc3:k_close_A = $ffc3
k_chkin = $ffc6:k_chkin_X = $ffc6
k_chkout = $ffc9:k_chkout_X = $ffc9:k_ckout = $ffc9
k_clrchn = $ffcc:k_clrch = $ffcc
k_chrin = $ffcf:k_basin = $ffcf
k_chrout = $ffd2:k_basout = $ffd2:k_bsout = $ffd2
k_load = $ffd5:k_load_AXY = $ffd5 ; A means verify, YYXX is desired load address (if channel == 0), returns end+1 in YYXX
k_save = $ffd8:k_save_AXY = $ffd8 ; A is zp address of start ptr(!), YYXX is end address (+1)
k_settim = $ffdb
k_rdtim = $ffde
k_stop = $ffe1
k_getin = $ffe4:k_get = $ffe4
k_clall = $ffe7
k_udtim = $ffea
k_scrorg = $ffed
k_plot = $fff0 ; get/set cursor (to set, clear carry)
k_iobase = $fff3
!address {
k_cint = $ff81
k_ioinit = $ff84
k_ramtas = $ff87
k_restor = $ff8a
k_vector = $ff8d
k_setmsg = $ff90
k_secnd = $ff93
k_tksa = $ff96
k_memtop = $ff99
k_membot = $ff9c
k_key = $ff9f
k_settmo = $ffa2
k_iecin = $ffa5:k_acptr = $ffa5
k_iecout = $ffa8:k_ciout = $ffa8
k_untalk = $ffab:k_untlk = $ffab
k_unlisten = $ffae:k_unlsn = $ffae
k_listen = $ffb1:k_listn = $ffb1
k_talk = $ffb4
k_readss = $ffb7
k_setlfs = $ffba
k_setnam = $ffbd ; A is length, X is ptr-low, Y is ptr-high
k_open = $ffc0
k_close = $ffc3:k_close_A = $ffc3
k_chkin = $ffc6:k_chkin_X = $ffc6
k_chkout = $ffc9:k_chkout_X = $ffc9:k_ckout = $ffc9
k_clrchn = $ffcc:k_clrch = $ffcc
k_chrin = $ffcf:k_basin = $ffcf
k_chrout = $ffd2:k_basout = $ffd2:k_bsout = $ffd2
k_load = $ffd5:k_load_AXY = $ffd5 ; A means verify, YYXX is desired load address (if channel == 0), returns end+1 in YYXX
k_save = $ffd8:k_save_AXY = $ffd8 ; A is zp address of start ptr(!), YYXX is end address (+1)
k_settim = $ffdb
k_rdtim = $ffde
k_stop = $ffe1
k_getin = $ffe4:k_get = $ffe4
k_clall = $ffe7
k_udtim = $ffea
k_scrorg = $ffed
k_plot = $fff0 ; get/set cursor (to set, clear carry)
k_iobase = $fff3
}

View File

@ -412,9 +412,12 @@ Examples:
Miscellaneous: The old syntax ("!for LABEL, END { BLOCK }" where
START was always implied to be 1) is still fully
supported, but gives a warning to get people to change
to the new syntax. When migrating your sources, bear
in mind that it is no longer possible to skip the
block completely by specifying a loop count of zero.
to the new syntax. You can disable this warning using
the "-Wno-old-for" switch, but then you will get
warnings for using the *new* syntax.
When migrating your sources, bear in mind that it is
no longer possible to skip the block completely by
specifying a loop count of zero.
Also note that with the new algorithm, LABEL has a
different value after the block than during the last
loop cycle, while the old algorithm kept that last
@ -811,6 +814,37 @@ Purpose: Assume short (8 bits) index registers. Only needed
pass.
----------------------------------------------------------------------
Section: Type system
----------------------------------------------------------------------
Call: !address [ { BLOCK } ]
or: !address LABEL = VALUE
Purpose: Mark a block or a statement as "explicitly defined
labels are holding addresses".
Parameters: BLOCK: A block of assembler statements
Everything inside the block will be parsed as usual,
but labels getting explicitly defined will be marked
as referencing memory.
If no block is given, only the current statement will
be affected, which should then be an explicit label
definition.
Aliases: "!addr"
Examples: !addr k_chrout = $ffd2 ; this is an address
CLEAR = 147 ; but this is not
!addr {
; these are addresses:
sid_v1_control = $d404
sid_v2_control = $d40b
sid_v3_control = $d412
}
; these are not:
sid_VOICECONTROL_NOISE = %#.......
sid_VOICECONTROL_RECTANGLE = %.#......
sid_VOICECONTROL_SAWTOOTH = %..#.....
sid_VOICECONTROL_TRIANGLE = %...#....
----------------------------------------------------------------------
Section: Obsolete pseudo opcodes (they will throw errors if used)
----------------------------------------------------------------------

View File

@ -12,6 +12,19 @@ platform used. There should be another help file in this archive
outlining the platform specific changes.
----------------------------------------------------------------------
Section: New in release 0.95
----------------------------------------------------------------------
Added an experimental type system to tell addresses and non-addresses
apart (per default disabled; must be activated using the
"-Wtype-mismatch" CLI switch). The new "!address" pseudo opcode is
used to mark label definitions as setting address values.
Added "-Wno-old-for" switch to disable warning about old "!for"
syntax. However, this will in turn enable warnings about using the
*new* syntax.
----------------------------------------------------------------------
Section: New in release 0.94.12
----------------------------------------------------------------------

View File

@ -55,9 +55,14 @@ Bug in ACME, code follows
C-style "==" comparison detected.
To check for equality, use a single '=' character instead.
Found deprecated "!for" syntax.
Found old "!for" syntax.
Please update your sources to use the new "!for" syntax. See
AllPOs.txt for details.
You can suppress this warning using the "-Wno-old-for" switch.
Found new "!for" syntax.
When using the "-Wno-old-for" switch to disable the warning about
the older syntax, the new syntax will trigger this warning.
Implicit label definition not in leftmost column.
An implicit label definition has blanks before the label name.
@ -128,6 +133,12 @@ Using oversized addressing mode.
always truncate a value to 8 bits, use the '<' operator).
More about the postfixing method can be found in "AddrModes.txt".
Wrong type - expected address.
Wrong type - expected integer.
These warnings are only given when type checking has been enabled
using the "-Wtype-mismatch" switch. Make sure the argument type
matches the instruction's addressing mode.
----------------------------------------------------------------------
Section: Errors during assembly

View File

@ -105,6 +105,8 @@ ACME exists on several platforms, meaning you can easily exchange your
sources with other people (preferring other OSes).
ACME can convert its strings to PetSCII and screen code (Okay, this is
C64-specific).
ACME has a rudimentary type checking system to catch errors like
missing '#' characters.
Did I mention that it is fast?

View File

@ -21,7 +21,9 @@ Section: Example of what an ACME source code file looks like
!to "tiny.o", cbm ; set output file and format
* = $c000 ; set program counter
basout = $ffd2 ; explicit global label def.
CLEAR = 147 ; a global label definition
!addr basout = $ffd2 ; another one, marked as an address
; a string output loop:
ldx #0
beq + ; enter loop
@ -46,8 +48,19 @@ Here's the same fragment again, now with some additional info:
; respectively.
* = $c000 ; set program counter
; This can also be done using the command line option "--setpc".
basout = $ffd2 ; explicit global label def.
; Now "basout" is defined as a global label having the value $ffd2.
; some global label definitions
CLEAR = 147 ; this is a simple constant
; Now "CLEAR" is defined as a global label having the value 147.
!addr basout = $ffd2 ; this gets marked as an address
; Now "basout" is defined as a global "address" type label having the
; value $ffd2.
; The distinction between addresses and non-addresses only
; matters when the type check system gets activated using
; the "-Wtype-mismatch" switch. Then, a line like
; "lda CLEAR" would trigger a type mismatch warning because
; of the missing '#' character.
; a string output loop:
ldx #0
beq + ; enter loop
@ -157,6 +170,9 @@ found in the file "AllPOs.txt". Here's just a short overview:
!warn !error !serious
...for generating warnings, errors and serious errors.
!addr
...to mark labels as addresses, for the optional type check system.
----------------------------------------------------------------------
Section: Command line arguments
@ -180,13 +196,13 @@ Available options are:
-l, --labeldump FILE select label dump file
This can also be given using the "!sl" pseudo opcode.
--setpc NUMBER set program counter
This can also be given in the source code using "* = NUMBER".
--cpu CPU_TYPE set processor type
This can be changed in the source code using the "!cpu" pseudo
opcode. Defaults to 6502.
--setpc NUMBER set program counter
This can also be given in the source code using "* = NUMBER".
--initmem NUMBER define 'empty' memory
This can also be given using the "!initmem" pseudo opcode.
Defaults to zero.
@ -200,22 +216,18 @@ Available options are:
-vDIGIT set verbosity level
Sets how much additional informational output is generated.
Higher values mean more output:
acme -v0 source.a
acme -v0 source.a
This is the default: No additional output is generated,
ACME will only display warnings and errors.
acme -v1 source.a
acme -v1 source.a
Now the start and end addresses of the generated output
file are displayed, along with its size (a CBM-style
"load address" is *not* counted).
acme -v2 source.a
acme -v2 source.a
In addition to the "-v1" output, ACME will announce each
pass, will show amount and offset of "!binary" loads, and
show start and end addresses and size of each segment.
acme -v3 source.a
acme -v3 source.a
In addition to the "-v2" output, ACME will now announce
each source file.
@ -226,9 +238,14 @@ Available options are:
(using conditional assembly in your source code file).
-W fine-tune amount and type of warnings
Currently only sub-option is supported: "-Wno-label-indent"
will switch off warnings about implicit label definitions not
being in the leftmost column.
-Wno-label-indent
Disables warnings about implicit label definitions not
being in the leftmost column.
-Wno-old-for
Disables warnings about the old "!for" syntax and at the
same time enables warnings about the _new_ "!for" syntax.
-Wtype-mismatch
Enables type checking system (warns about wrong types).
--use-stdout fix for 'Relaunch64' IDE
With this option, errors are written to the standard output
@ -265,6 +282,7 @@ This is a list of the operators currently known by ACME:
14 arcsin(v) Inverse of sin()
14 arccos(v) Inverse of cos()
14 arctan(v) Inverse of tan()
14 addr(v) Mark as address
14 int(v) Convert to integer
14 float(v) Convert to float
13 ! v Complement of NOT

View File

@ -1,4 +1,4 @@
;ACME 0.94
;ACME 0.95
;!sl "ddrv.l"
; Name DuoDriver
; Purpose Input driver for mouse and joystick
@ -26,6 +26,7 @@
; 26 Mar 2006 Release 4.03. Adjusted source to ACME 0.91 capabilities.
; 25 Nov 2007 Release 4.04. Adjusted source to ACME 0.94 capabilities.
; 7 Apr 2013 Slightly reformatted.
; 1 Jun 2014 Adjusted to experimental type system of ACME 0.95
; This source code file uses conditional assembly
; to decide which version to produce (C64 or C128).
@ -47,12 +48,12 @@
!if SYSTEM = 64 {
* = $c000
!to "ddrv64.prg", cbm
VIC_Base = $d000
!addr VIC_Base = $d000
}
!if SYSTEM = 128 {
* = $0c00
!to "ddrv128.prg", cbm
VIC_Base = $11d6 ; Location of mirror registers
!addr VIC_Base = $11d6 ; Location of mirror registers
}
; Pointer's maximum coordinates
@ -78,11 +79,14 @@
; Locations to store button states, $ff = pressed, $00 = not pressed.
; Mouse uses both buttons, joystick only uses "LeftButton".
; Location to store pointer's current character coordinates.
!addr {
!if SYSTEM = 64 {
LeftButton = $a4
RightButton = $a5
CharX = $b3
CharY = $b4
tapebuf = $0340
spr_ptrs = 2040
}
!if SYSTEM = 128 {
LeftButton = $fa
@ -96,7 +100,6 @@
; x low, x high, y low, y high
Coordinates = $fb ; $fb..$fe
; --- System constants
; Interrupt vector
@ -108,7 +111,7 @@
cia1_prb = $dc01
cia1_ddrb = $dc03
mmu_cr = $ff00 ; c128 only
};addr
; --- Label definitions
@ -168,15 +171,15 @@ Init lda sys_iirq
; Copy sprites to tape buffer
ldx #127
- lda Sprites, x
sta $0340, x
sta tapebuf, x
dex
bpl -
lda #Sprites_Bitmask
; Set sprite block pointers
ldx #$0d
stx 2040 + Sprite_A
stx spr_ptrs + Sprite_A
inx
stx 2040 + Sprite_B
stx spr_ptrs + Sprite_B
; Activate pointer sprites
ora VIC_Base + 21
sta VIC_Base + 21
@ -419,7 +422,7 @@ StoreOF sta Sprites_OF ; set x overflow
; The initialisation routine sets the argument to the address of the
; previous IRQ routine.
mod16 = * + 1: jmp $ffff ; (self-modifying)
mod16 = * + 1: jmp addr($ffff) ; (self-modifying)
; This table is for part 8.
;OrTable !byte 0, 32, 64 ; VDC only

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
; ist der komplette Sourcecode von MacEdit
; (80-Zeichen-Version)
; Version 0.7
@ -76,3 +76,5 @@ Spätere Änderungen am Source:
Converted to UTF-8
27 Jun 2013:
Adjusted to change in library.
1 Jun 2014:
Adjusted to experimental type system of ACME 0.95

View File

@ -1,10 +1,10 @@
;ACME 0.94.4
;ACME 0.95
; Konstanten:
FALSE = 0 ; Das Programm verläßt sich an etlichen Stellen
TRUE = $ff ; darauf, daß genau diese Werte zugewiesen wurden.
MODIFIED8 = $ff ; Defaultwerte für
MODIFIED16 = $ffff ; Selbstmodifikationen
!addr MODIFIED16 = $ffff ; Selbstmodifikationen
Char_NUL = $00
Char_STOP = $03
@ -46,6 +46,7 @@
lf = 8 ; Filenr. & Sek.-Addy
; Zeropage:
!addr {
D8502 = $00 ; Direction
R8502 = $01 ; Register
vvek = $83 ; Vektor auf LineVektor
@ -91,3 +92,4 @@
clrchn = $ffcc
basin = $ffcf
basout = $ffd2
}

View File

@ -1,4 +1,4 @@
;ACME 0.94.4
;ACME 0.95
!zone
F_info ldx #hWindow_InfoBox
@ -483,7 +483,7 @@ swin !byte 0 ; Auch fuer 'lwin'
bckgrnd = 26 ; screencolor-register
flnmpos = 87 ; filenameposition
wsstart = $0fd0 ; windowstack-start
tcolor = $f2 ; attribute-buffer
!addr tcolor = $f2 ; attribute-buffer
; Subs:
!zone
@ -505,11 +505,11 @@ init ldx repeatedtry ; first start ?
stx fnbank ; filename-CR
dex
stx locks ; 'CBM-shift' off
stx $0ac5 ; 'ASC/DIN' off
stx addr($0ac5) ; 'ASC/DIN' off
stx basic ; 'Basic-IRQ' off
jsr crsrinit ; init crsr
ldx #$0b ; VIC off
stx $11e7
stx addr($11e7)
lda mode ; which mode ?
bmi + ; if 40 then
jsr kernel_switchmode ; switch mode
@ -567,7 +567,7 @@ init ldx repeatedtry ; first start ?
sta conreg + 1 ; full RAM
ldx #$0b ; loop for new
- lda keyb, x ; keyboard-tabs
sta $033e, x
sta addr($033e), x
dex
bpl -
jsr handleid ; old ID ?
@ -747,7 +747,7 @@ F_gosys +bank15
jsr kernel_cls ; CLS
lda #0 ; '0' for
sta locks ; 'CBM-Shift' on
sta $0ac5 ; 'ASC/DIN' on
sta addr($0ac5) ; 'ASC/DIN' on
sta basic ; 'Basic-IRQ' on
lda nmibuf ; restore NMI
ldx nmibuf + 1

View File

@ -8,7 +8,7 @@ RM = rm
PROGS = acme
BINDIR = /usr/local/bin
USERBIN = $(HOME)/bin
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
all: $(PROGS)
@ -49,6 +49,8 @@ section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c
clean:
-$(RM) -f *.o $(PROGS) *~ core

View File

@ -8,7 +8,7 @@ RM = rm
PROGS = acme
#BINDIR = /usr/local/bin
#USERBIN = $(HOME)/bin
OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o
OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
all: $(PROGS)
@ -50,6 +50,8 @@ section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c
clean:
del *.o
# -$(RM) -f *.o $(PROGS) *~ core

View File

@ -15,8 +15,8 @@ USERBIN = $(HOME)/bin
all: $(PROGS)
acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o _dos.o resource.res
$(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o resource.res
acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o_dos.o resource.res
$(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o resource.res
strip acme.exe
@ -53,6 +53,8 @@ section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c
# _dos.o: _dos.h
win/resource.rc: acme.c

View File

@ -8,7 +8,7 @@ RM = rm
PROGS = acme
#BINDIR = /usr/local/bin
#USERBIN = $(HOME)/bin
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
all: $(PROGS)
@ -50,6 +50,8 @@ section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c
clean:
wipe o.* ~c
# -$(RM) -f *.o $(PROGS) *~ core

View File

@ -15,9 +15,9 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define RELEASE "0.94.12" // update before release (FIXME)
#define CODENAME "Zarquon" // update before release
#define CHANGE_DATE "31 May" // update before release
#define RELEASE "0.95" // update before release (FIXME)
#define CODENAME "Fenchurch" // update before release
#define CHANGE_DATE "2 Jun" // update before release
#define CHANGE_YEAR "2014" // update before release
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
@ -64,6 +64,8 @@ static const char name_dumpfile[] = "label dump filename";
#define OPTION_VERSION "version"
// options for "-W"
#define OPTIONWNO_LABEL_INDENT "no-label-indent"
#define OPTIONWNO_OLD_FOR "no-old-for"
#define OPTIONWTYPE_MISMATCH "type-mismatch"
// variables
@ -126,6 +128,8 @@ static void show_help_and_exit(void)
// as long as there is only one -W option:
#define OPTIONWNO_LABEL_INDENT "no-label-indent"
" -W" OPTIONWNO_LABEL_INDENT " suppress warnings about indented labels\n"
" -W" OPTIONWNO_OLD_FOR " suppress warnings about old \"!for\" syntax\n"
" -W" OPTIONWTYPE_MISMATCH " enable type checking (warn about type mismatch)\n"
// when there are more, use next line and add a separate function:
//" -W show warning level options\n"
" --" OPTION_USE_STDOUT " fix for 'Relaunch64' IDE (see docs)\n"
@ -425,6 +429,12 @@ static char short_option(const char *argument)
if (strcmp(argument + 1, OPTIONWNO_LABEL_INDENT) == 0) {
warn_on_indented_labels = FALSE;
goto done;
} else if (strcmp(argument + 1, OPTIONWNO_OLD_FOR) == 0) {
warn_on_old_for = FALSE;
goto done;
} else if (strcmp(argument + 1, OPTIONWTYPE_MISMATCH) == 0) {
warn_on_type_mismatch = TRUE;
goto done;
} else {
fprintf(stderr, "%sUnknown warning level.\n", cliargs_error);
exit(EXIT_FAILURE);

126
src/alu.c
View File

@ -48,6 +48,7 @@ enum operator_handle {
OPHANDLE_END, // "reached end of expression"
OPHANDLE_RETURN, // "return value to caller"
// functions
OPHANDLE_ADDR, // addr(v)
OPHANDLE_INT, // int(v)
OPHANDLE_FLOAT, // float(v)
OPHANDLE_SIN, // sin(v)
@ -129,6 +130,7 @@ static struct operator ops_negate = {OPHANDLE_NEGATE, 28}; // monadic
static struct operator ops_powerof = {OPHANDLE_POWEROF, 29}; // dyadic, right-associative
static struct operator ops_not = {OPHANDLE_NOT, 30}; // monadic
// function calls act as if they were monadic operators
static struct operator ops_addr = {OPHANDLE_ADDR, 32}; // function
static struct operator ops_int = {OPHANDLE_INT, 32}; // function
static struct operator ops_float = {OPHANDLE_FLOAT, 32}; // function
static struct operator ops_sin = {OPHANDLE_SIN, 32}; // function
@ -176,6 +178,7 @@ static struct node_t operator_list[] = {
};
static struct node_t *function_tree = NULL; // tree to hold functions
static struct node_t function_list[] = {
PREDEFNODE("addr", &ops_addr),
PREDEFNODE("int", &ops_int),
PREDEFNODE("float", &ops_float),
PREDEFNODE(s_arcsin, &ops_arcsin),
@ -193,18 +196,22 @@ static struct node_t function_list[] = {
#define RIGHT_INTVAL (operand_stack[operand_sp-1].val.intval)
#define LEFT_FPVAL (operand_stack[operand_sp-2].val.fpval)
#define RIGHT_FPVAL (operand_stack[operand_sp-1].val.fpval)
#define LEFT_ADDRREFS (operand_stack[operand_sp-2].addr_refs)
#define RIGHT_ADDRREFS (operand_stack[operand_sp-1].addr_refs)
#define PUSH_OPERATOR(x) operator_stack[operator_sp++] = (x)
#define PUSH_INTOPERAND(i, f) \
#define PUSH_INTOPERAND(i, f, r) \
do { \
operand_stack[operand_sp].flags = (f); \
operand_stack[operand_sp++].val.intval = (i); \
operand_stack[operand_sp].val.intval = (i); \
operand_stack[operand_sp++].addr_refs = (r); \
} while (0)
#define PUSH_FPOPERAND(fp, f) \
do { \
operand_stack[operand_sp].flags = (f) | MVALUE_IS_FP; \
operand_stack[operand_sp++].val.fpval = (fp); \
operand_stack[operand_sp].val.fpval = (fp); \
operand_stack[operand_sp++].addr_refs = 0; \
} while (0)
@ -353,7 +360,7 @@ static void parse_quoted_character(char closing_quote)
Throw_error("There's more than one character.");
Input_skip_remainder();
}
PUSH_INTOPERAND(value, MVALUE_GIVEN | MVALUE_ISBYTE);
PUSH_INTOPERAND(value, MVALUE_GIVEN | MVALUE_ISBYTE, 0);
// Now GotByte = char following closing quote (or CHAR_EOS on error)
}
@ -393,7 +400,7 @@ static void parse_binary_value(void) // Now GotByte = "%" or "b"
flags |= MVALUE_FORCE16;
}
}
PUSH_INTOPERAND(value, flags);
PUSH_INTOPERAND(value, flags, 0);
// Now GotByte = non-binary char
}
@ -437,7 +444,7 @@ static void parse_hexadecimal_value(void) // Now GotByte = "$" or "x"
flags |= MVALUE_FORCE16;
}
}
PUSH_INTOPERAND(value, flags);
PUSH_INTOPERAND(value, flags, 0);
// Now GotByte = non-hexadecimal char
}
@ -497,7 +504,7 @@ static void parse_decimal_value(void) // Now GotByte = first digit
GetByte();
parse_frac_part(intval);
} else {
PUSH_INTOPERAND(intval, MVALUE_GIVEN);
PUSH_INTOPERAND(intval, MVALUE_GIVEN, 0);
}
// Now GotByte = non-decimal char
}
@ -527,7 +534,7 @@ static void parse_octal_value(void) // Now GotByte = "&"
flags |= MVALUE_FORCE16;
}
}
PUSH_INTOPERAND(value, flags);
PUSH_INTOPERAND(value, flags, 0);
// Now GotByte = non-octal char
}
@ -535,11 +542,11 @@ static void parse_octal_value(void) // Now GotByte = "&"
// Parse program counter ('*')
static void parse_program_counter(void) // Now GotByte = "*"
{
struct result_int_t pc;
struct result_t pc;
GetByte();
vcpu_read_pc(&pc);
PUSH_INTOPERAND(pc.intval, pc.flags | MVALUE_EXISTS);
PUSH_INTOPERAND(pc.val.intval, pc.flags | MVALUE_EXISTS, pc.addr_refs);
}
@ -698,7 +705,7 @@ static void expect_operand_or_monadic_operator(void)
}
} else {
// illegal character read - so don't go on
PUSH_INTOPERAND(0, 0);
PUSH_INTOPERAND(0, 0, 0); // push dummy operand so stack is ok
// push pseudo value, EXISTS flag is clear
if (operator_stack[operator_sp-1] == &ops_return) {
PUSH_OPERATOR(&ops_end);
@ -840,7 +847,7 @@ static void expect_dyadic_operator(void)
//break; unreachable
// end of expression or text version of dyadic operator
default:
// check string version of operators
// check string versions of operators
if (BYTEFLAGS(GotByte) & STARTS_KEYWORD) {
Input_read_and_lower_keyword();
// Now GotByte = illegal char
@ -878,6 +885,7 @@ static void perform_fp(double (*fn)(double))
RIGHT_FLAGS |= MVALUE_IS_FP;
}
RIGHT_FPVAL = fn(RIGHT_FPVAL);
RIGHT_ADDRREFS = 0; // result now is a non-address
}
@ -895,6 +903,7 @@ static void perform_ranged_fp(double (*fn)(double))
Throw_error("Argument out of range.");
RIGHT_FPVAL = 0;
}
RIGHT_ADDRREFS = 0; // result now is a non-address
}
@ -918,7 +927,7 @@ static void both_ensure_int(int warn)
RIGHT_INTVAL = RIGHT_FPVAL;
RIGHT_FLAGS &= ~MVALUE_IS_FP;
}
// FIXME - "warn" is not used
// FIXME - warning is never seen if both operands are undefined in first pass!
Throw_first_pass_warning("Converted to integer for binary logic operator.");
}
@ -993,9 +1002,14 @@ static void try_to_reduce_stacks(int *open_parentheses)
goto remove_next_to_last_operator;
// functions
case OPHANDLE_ADDR:
RIGHT_ADDRREFS = 1; // result now is an address
goto remove_next_to_last_operator;
case OPHANDLE_INT:
if (RIGHT_FLAGS & MVALUE_IS_FP)
right_fp_to_int();
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator;
case OPHANDLE_FLOAT:
@ -1004,30 +1018,31 @@ static void try_to_reduce_stacks(int *open_parentheses)
RIGHT_FPVAL = RIGHT_INTVAL;
RIGHT_FLAGS |= MVALUE_IS_FP;
}
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator;
case OPHANDLE_SIN:
perform_fp(sin);
perform_fp(sin); // also zeroes addr_refs
goto remove_next_to_last_operator;
case OPHANDLE_COS:
perform_fp(cos);
perform_fp(cos); // also zeroes addr_refs
goto remove_next_to_last_operator;
case OPHANDLE_TAN:
perform_fp(tan);
perform_fp(tan); // also zeroes addr_refs
goto remove_next_to_last_operator;
case OPHANDLE_ARCSIN:
perform_ranged_fp(asin);
perform_ranged_fp(asin); // also zeroes addr_refs
goto remove_next_to_last_operator;
case OPHANDLE_ARCCOS:
perform_ranged_fp(acos);
perform_ranged_fp(acos); // also zeroes addr_refs
goto remove_next_to_last_operator;
case OPHANDLE_ARCTAN:
perform_fp(atan);
perform_fp(atan); // also zeroes addr_refs
goto remove_next_to_last_operator;
// monadic operators
@ -1055,6 +1070,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
RIGHT_INTVAL = (RIGHT_INTVAL) & 255;
RIGHT_FLAGS |= MVALUE_ISBYTE;
RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator;
case OPHANDLE_HIGHBYTEOF:
@ -1064,6 +1080,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
RIGHT_INTVAL = ((RIGHT_INTVAL) >> 8) & 255;
RIGHT_FLAGS |= MVALUE_ISBYTE;
RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator;
case OPHANDLE_BANKBYTEOF:
@ -1073,6 +1090,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
RIGHT_INTVAL = ((RIGHT_INTVAL) >> 16) & 255;
RIGHT_FLAGS |= MVALUE_ISBYTE;
RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator;
// dyadic operators
@ -1080,6 +1098,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) {
both_ensure_fp();
LEFT_FPVAL = pow(LEFT_FPVAL, RIGHT_FPVAL);
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
}
@ -1090,6 +1109,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
Throw_error("Exponent is negative.");
LEFT_INTVAL = 0;
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_MULTIPLY:
@ -1099,6 +1119,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL *= RIGHT_INTVAL;
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_DIVIDE:
@ -1120,6 +1141,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
LEFT_INTVAL = 0;
}
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_INTDIV:
@ -1142,6 +1164,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
LEFT_INTVAL = 0;
}
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_MODULO:
@ -1154,6 +1177,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
Throw_error(exception_div_by_zero);
LEFT_INTVAL = 0;
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_ADD:
@ -1163,6 +1187,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL += RIGHT_INTVAL;
}
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
goto handle_flags_and_dec_stacks;
case OPHANDLE_SUBTRACT:
@ -1172,6 +1197,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL -= RIGHT_INTVAL;
}
LEFT_ADDRREFS -= RIGHT_ADDRREFS; // subtract address references
goto handle_flags_and_dec_stacks;
case OPHANDLE_SL:
@ -1181,6 +1207,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
LEFT_FPVAL *= pow(2.0, RIGHT_INTVAL);
else
LEFT_INTVAL <<= RIGHT_INTVAL;
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_ASR:
@ -1190,6 +1217,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
LEFT_FPVAL /= (1 << RIGHT_INTVAL);
else
LEFT_INTVAL = my_asr(LEFT_INTVAL, RIGHT_INTVAL);
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_LSR:
@ -1197,6 +1225,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
both_ensure_int(TRUE);
LEFT_INTVAL = ((uintval_t) LEFT_INTVAL) >> RIGHT_INTVAL;
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_LE:
@ -1206,6 +1235,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL = (LEFT_INTVAL <= RIGHT_INTVAL);
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_LESSTHAN:
@ -1215,6 +1245,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL = (LEFT_INTVAL < RIGHT_INTVAL);
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_GE:
@ -1224,6 +1255,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL = (LEFT_INTVAL >= RIGHT_INTVAL);
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_GREATERTHAN:
@ -1233,6 +1265,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL = (LEFT_INTVAL > RIGHT_INTVAL);
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_NOTEQUAL:
@ -1242,6 +1275,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL = (LEFT_INTVAL != RIGHT_INTVAL);
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_EQUALS:
@ -1251,6 +1285,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else {
LEFT_INTVAL = (LEFT_INTVAL == RIGHT_INTVAL);
}
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks;
case OPHANDLE_AND:
@ -1258,6 +1293,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
both_ensure_int(TRUE);
LEFT_INTVAL &= RIGHT_INTVAL;
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
goto handle_flags_and_dec_stacks;
case OPHANDLE_EOR:
@ -1268,6 +1304,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
both_ensure_int(TRUE);
LEFT_INTVAL ^= RIGHT_INTVAL;
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
goto handle_flags_and_dec_stacks;
case OPHANDLE_OR:
@ -1275,6 +1312,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
both_ensure_int(TRUE);
LEFT_INTVAL |= RIGHT_INTVAL;
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
goto handle_flags_and_dec_stacks;
default:
@ -1389,8 +1427,7 @@ static int parse_expression(struct result_t *result)
}
// These functions handle numerical expressions. There are operators for
// arithmetic, logic, shift and comparison operations.
// These functions handle numerical expressions.
// There are several different ways to call the core function:
// intval_t ALU_any_int(void);
// returns int value (0 if result was undefined)
@ -1473,23 +1510,19 @@ int ALU_optional_defined_int(intval_t *target)
// It the result's "exists" flag is clear (=empty expression), it throws an
// error.
// If the result's "defined" flag is clear, result_is_undefined() is called.
void ALU_int_result(struct result_int_t *intresult)
void ALU_int_result(struct result_t *intresult)
{
struct result_t result;
if (parse_expression(&result))
if (parse_expression(intresult))
Throw_error(exception_paren_open);
if ((result.flags & MVALUE_EXISTS) == 0)
Throw_error(exception_no_value);
else if ((result.flags & MVALUE_DEFINED) == 0)
result_is_undefined();
if (result.flags & MVALUE_IS_FP) {
intresult->intval = result.val.fpval;
intresult->flags = result.flags & ~MVALUE_IS_FP;
} else {
intresult->intval = result.val.intval;
intresult->flags = result.flags;
// make sure result is not float
if (intresult->flags & MVALUE_IS_FP) {
intresult->val.intval = intresult->val.fpval;
intresult->flags &= ~MVALUE_IS_FP;
}
if ((intresult->flags & MVALUE_EXISTS) == 0)
Throw_error(exception_no_value);
else if ((intresult->flags & MVALUE_DEFINED) == 0)
result_is_undefined();
}
@ -1497,26 +1530,23 @@ void ALU_int_result(struct result_int_t *intresult)
// This function allows for one '(' too many. Needed when parsing indirect
// addressing modes where internal indices have to be possible. Returns number
// of parentheses still open (either 0 or 1).
int ALU_liberal_int(struct result_int_t *intresult)
int ALU_liberal_int(struct result_t *intresult)
{
struct result_t result;
int parentheses_still_open;
int parentheses_still_open;
parentheses_still_open = parse_expression(&result);
parentheses_still_open = parse_expression(intresult);
// make sure result is not float
if (intresult->flags & MVALUE_IS_FP) {
intresult->val.intval = intresult->val.fpval;
intresult->flags &= ~MVALUE_IS_FP;
}
if (parentheses_still_open > 1) {
parentheses_still_open = 0;
Throw_error(exception_paren_open);
}
if ((result.flags & MVALUE_EXISTS)
&& ((result.flags & MVALUE_DEFINED) == 0))
if ((intresult->flags & MVALUE_EXISTS)
&& ((intresult->flags & MVALUE_DEFINED) == 0))
result_is_undefined();
if (result.flags & MVALUE_IS_FP) {
intresult->intval = result.val.fpval;
intresult->flags = result.flags & ~MVALUE_IS_FP;
} else {
intresult->intval = result.val.intval;
intresult->flags = result.flags;
}
return parentheses_still_open;
}

View File

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2009 Marco Baye
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// ALU stuff (the expression parser)
@ -12,9 +12,9 @@
// constants
// meaning of bits in "flags" of result_t and result_int_t structures:
// meaning of bits in "flags" of result_t structure:
#define MVALUE_IS_FP (1u << 8)
// floating point value (never set in result_int_t)
// floating point value
#define MVALUE_INDIRECT (1u << 7)
// needless parentheses indicate use of indirect addressing modes
#define MVALUE_EXISTS (1u << 6)
@ -50,9 +50,9 @@ extern intval_t ALU_defined_int(void);
// stores int value if given. Returns whether stored. Throws error if undefined.
extern int ALU_optional_defined_int(intval_t *);
// stores int value and flags (floats are transformed to int)
extern void ALU_int_result(struct result_int_t *);
extern void ALU_int_result(struct result_t *);
// stores int value and flags, allowing for one '(' too many (x-indirect addr)
extern int ALU_liberal_int(struct result_int_t *);
extern int ALU_liberal_int(struct result_t *);
// stores value and flags (result may be either int or float)
extern void ALU_any_result(struct result_t *);

View File

@ -14,6 +14,7 @@
#include "global.h"
#include "output.h"
#include "tree.h"
#include "typesystem.h"
// constants
@ -139,6 +140,19 @@ static enum eos PO_fill(void)
}
// force explicit label definitions to set "address" flag ("!addr"). Has to be re-entrant.
static enum eos PO_addr(void) // Now GotByte = illegal char
{
SKIPSPACE();
if (GotByte == CHAR_SOB) {
typesystem_force_address_block();
return ENSURE_EOS;
}
typesystem_force_address_statement(TRUE);
return PARSE_REMAINDER;
}
// show user-defined message
static enum eos throw_string(const char prefix[], void (*fn)(const char *))
{
@ -240,6 +254,8 @@ static struct node_t pseudo_opcodes[] = {
PREDEFNODE("binary", PO_binary),
PREDEFNODE("fi", PO_fill),
PREDEFNODE("fill", PO_fill),
PREDEFNODE("addr", PO_addr),
PREDEFNODE("address", PO_addr),
// PREDEFNODE("debug", PO_debug),
// PREDEFNODE("info", PO_info),
// PREDEFNODE("print", PO_print),

View File

@ -18,11 +18,7 @@ struct result_t { // either int or float
intval_t intval; // integer value
double fpval; // floating point value
} val; // Expression value
};
// result structure type definition for int
struct result_int_t {
int flags; // expression flags
intval_t intval; // expression value
int addr_refs; // address reference count (only look at this if value is DEFINED)
};

View File

@ -75,7 +75,7 @@ static enum eos PO_align(void)
intval_t and,
equal,
fill,
test = CPU_state.pc.intval;
test = CPU_state.pc.val.intval;
// make sure PC is defined.
if ((CPU_state.pc.flags & MVALUE_DEFINED) == 0) {
@ -152,13 +152,13 @@ static enum eos PO_pseudopc(void)
// set new
new_pc = ALU_defined_int(); // FIXME - allow for undefined!
new_offset = (new_pc - CPU_state.pc.intval) & 0xffff;
CPU_state.pc.intval = new_pc;
new_offset = (new_pc - CPU_state.pc.val.intval) & 0xffff;
CPU_state.pc.val.intval = new_pc;
CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined!
// if there's a block, parse that and then restore old value!
if (Parse_optional_block()) {
// restore old
CPU_state.pc.intval = (CPU_state.pc.intval - new_offset) & 0xffff;
CPU_state.pc.val.intval = (CPU_state.pc.val.intval - new_offset) & 0xffff;
CPU_state.pc.flags = outer_flags;
} else {
// not using a block is no longer allowed

View File

@ -209,12 +209,15 @@ static enum eos PO_for(void) // Now GotByte = illegal char
first_arg = ALU_defined_int();
if (Input_accept_comma()) {
old_algo = FALSE; // new format - yay!
if (!warn_on_old_for)
Throw_first_pass_warning("Found new \"!for\" syntax.");
counter_first = first_arg; // use given argument
counter_last = ALU_defined_int(); // read second argument
counter_increment = (counter_last < counter_first) ? -1 : 1;
} else {
old_algo = TRUE; // old format - booo!
Throw_first_pass_warning("Found deprecated \"!for\" syntax.");
if (warn_on_old_for)
Throw_first_pass_warning("Found old \"!for\" syntax.");
if (first_arg < 0)
Throw_serious_error("Loop count is negative.");
counter_first = 0; // CAUTION - old algo pre-increments and therefore starts with 1!

View File

@ -5,6 +5,7 @@
// Global stuff - things that are needed by several modules
// 4 Oct 2006 Fixed a typo in a comment
// 22 Nov 2007 Added warn_on_indented_labels
// 2 Jun 2014 Added warn_on_old_for and warn_on_type_mismatch
#include <stdio.h>
#include "platform.h"
#include "acme.h"
@ -17,6 +18,7 @@
#include "output.h"
#include "section.h"
#include "tree.h"
#include "typesystem.h"
// constants
@ -55,7 +57,7 @@ const char exception_syntax[] = "Syntax error.";
// ...4.... special character for input syntax: 0x00 TAB LF CR SPC : ; }
// ....3... preceding sequence of '-' characters is anonymous backward
// label. Currently only set for ')', ',' and CHAR_EOS.
// .....210 unused
// .....210 currently unused
const char Byte_flags[256] = {
/*$00*/ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// control characters
0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,
@ -98,6 +100,8 @@ int pass_count; // number of current pass (starts 0)
char GotByte; // Last byte read (processed)
int Process_verbosity = 0; // Level of additional output
int warn_on_indented_labels = TRUE; // warn if indented label is encountered
int warn_on_old_for = TRUE; // warn if "!for" with old syntax is found
int warn_on_type_mismatch = FALSE; // use type-checking system
// global counters
int pass_undefined_count; // "NeedValue" type errors
int pass_real_errors; // Errors yet
@ -256,9 +260,10 @@ void Parse_until_eob_or_eof(void)
while ((GotByte != CHAR_EOB) && (GotByte != CHAR_EOF)) {
// process one statement
statement_flags = 0; // no "label = pc" definition yet
typesystem_force_address_statement(FALSE);
// Parse until end of statement. Only loops if statement
// contains "label = pc" definition and something else; or
// if "!ifdef" is true.
// if "!ifdef" is true, or if "!addr" is used without block.
do {
switch (GotByte) {
case CHAR_EOS: // end of statement

View File

@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2009 Marco Baye
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// Global stuff - things that are needed by several modules
@ -47,7 +47,7 @@ extern const char Byte_flags[];
// converted to lower case by OR-ing this bit(!)
#define BYTEIS_SYNTAX (1u << 4) // special character for input syntax
#define FOLLOWS_ANON (1u << 3) // preceding '-' are backward label
// bits 2, 1 and 0 are unused
// bits 2, 1 and 0 are currently unused
// Variables
@ -64,6 +64,8 @@ enum eos {
extern int pass_count;
extern int Process_verbosity; // Level of additional output
extern int warn_on_indented_labels; // warn if indented label is encountered
extern int warn_on_old_for; // warn if "!for" with old syntax is found
extern int warn_on_type_mismatch; // use type-checking system
extern char GotByte; // Last byte read (processed)
// Global counters
extern int pass_undefined_count; // "NeedValue" type errors in current pass

View File

@ -17,6 +17,7 @@
#include "platform.h"
#include "section.h"
#include "tree.h"
#include "typesystem.h"
// constants
@ -62,7 +63,7 @@ static void dump_one_label(struct node_ra_t *node, FILE *fd)
}
// Search for label. Create if nonexistant. If created, give it flags "Flags".
// Search for label. Create if nonexistant. If created, give it flags "flags".
// The label name must be held in GlobalDynaBuf.
struct label *Label_find(zone_t zone, int flags)
{
@ -78,6 +79,7 @@ struct label *Label_find(zone_t zone, int flags)
label = safe_malloc(sizeof(*label));
// Finish empty label item
label->result.flags = flags;
label->result.addr_refs = 0;
if (flags & MVALUE_IS_FP)
label->result.val.fpval = 0;
else
@ -206,9 +208,9 @@ static struct node_t pseudo_opcodes[] = {
// GlobalDynaBuf holds the label name.
void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change)
{
struct result_int_t pc;
struct result_t result;
struct label *label;
struct result_t pc,
result;
struct label *label;
label = Label_find(zone, force_bit);
// implicit label definition (label)
@ -216,7 +218,8 @@ void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int c
Throw_first_pass_warning("Implicit label definition not in leftmost column.");
vcpu_read_pc(&pc);
result.flags = pc.flags & MVALUE_DEFINED;
result.val.intval = pc.intval;
result.val.intval = pc.val.intval;
result.addr_refs = pc.addr_refs;
Label_set_value(label, &result, change);
}
@ -236,6 +239,9 @@ void Label_parse_definition(zone_t zone, int stat_flags)
// label = parsed value
GetByte(); // skip '='
ALU_any_result(&result);
// if wanted, mark as address reference
if (typesystem_says_address())
result.addr_refs = 1;
Label_set_value(label, &result, FALSE);
Input_ensure_EOS();
} else {

View File

@ -11,6 +11,7 @@
#include "input.h"
#include "output.h"
#include "tree.h"
#include "typesystem.h"
// Constants
@ -395,9 +396,9 @@ static int get_index(int next)
return addressing_mode;
}
// This function stores the command's argument in the given result_int_t
// This function stores the command's argument in the given result_t
// structure (using the valueparser). The addressing mode is returned.
static int get_argument(struct result_int_t *result)
static int get_argument(struct result_t *result)
{
int open_paren,
addressing_mode = HAM_ABS;
@ -407,6 +408,7 @@ static int get_argument(struct result_int_t *result)
case '[':
GetByte(); // proceed with next char
ALU_int_result(result);
typesystem_want_addr(result);
if (GotByte == ']')
addressing_mode |= HAM_LIND | get_index(TRUE);
else
@ -416,10 +418,12 @@ static int get_argument(struct result_int_t *result)
GetByte(); // proceed with next char
addressing_mode |= HAM_IMM;
ALU_int_result(result);
typesystem_want_imm(result);
break;
default:
// liberal, to allow for "(...,"
open_paren = ALU_liberal_int(result);
typesystem_want_addr(result);
// check for implied addressing
if ((result->flags & MVALUE_EXISTS) == 0)
addressing_mode |= HAM_IMP;
@ -447,7 +451,7 @@ static int get_argument(struct result_int_t *result)
// Helper function for calc_arg_size()
// Only call with "size_bit = MVALUE_FORCE16" or "size_bit = MVALUE_FORCE24"
static int check_oversize(int size_bit, struct result_int_t *argument)
static int check_oversize(int size_bit, struct result_t *argument)
{
// only check if value is *defined*
if ((argument->flags & MVALUE_DEFINED) == 0)
@ -456,11 +460,11 @@ static int check_oversize(int size_bit, struct result_int_t *argument)
// value is defined, so check
if (size_bit == MVALUE_FORCE16) {
// check 16-bit argument for high byte zero
if ((argument->intval <= 255) && (argument->intval >= -128))
if ((argument->val.intval <= 255) && (argument->val.intval >= -128))
Throw_warning(exception_highbyte_zero);
} else {
// check 24-bit argument for bank byte zero
if ((argument->intval <= 65535) && (argument->intval >= -32768))
if ((argument->val.intval <= 65535) && (argument->val.intval >= -32768))
Throw_warning(exception_highbyte_zero);
}
return size_bit; // pass on result
@ -474,7 +478,7 @@ static int check_oversize(int size_bit, struct result_int_t *argument)
// argument value and flags of parameter
// addressing_modes adressing modes (8b, 16b, 24b or any combination)
// Return value = force bit for number of parameter bytes to send (0 = error)
static int calc_arg_size(int force_bit, struct result_int_t *argument, int addressing_modes)
static int calc_arg_size(int force_bit, struct result_t *argument, int addressing_modes)
{
// if there are no possible addressing modes, complain
if (addressing_modes == MAYBE______) {
@ -541,18 +545,18 @@ static int calc_arg_size(int force_bit, struct result_int_t *argument, int addre
// Value is sure, so use its own size
// if value is negative, size cannot be chosen. Complain!
if (argument->intval < 0) {
if (argument->val.intval < 0) {
Throw_error("Negative value - cannot choose addressing mode.");
return 0;
}
// Value is positive or zero. Check size ranges
// if there is an 8-bit addressing mode and value fits, use 8 bits
if ((addressing_modes & MVALUE_FORCE08) && (argument->intval < 256))
if ((addressing_modes & MVALUE_FORCE08) && (argument->val.intval < 256))
return MVALUE_FORCE08;
// if there is a 16-bit addressing mode and value fits, use 16 bits
if ((addressing_modes & MVALUE_FORCE16) && (argument->intval < 65536))
if ((addressing_modes & MVALUE_FORCE16) && (argument->val.intval < 65536))
return MVALUE_FORCE16;
// if there is a 24-bit addressing mode, use that. In case the
@ -584,16 +588,17 @@ static void not_in_bank(intval_t target)
// Mnemonics using only 8bit relative addressing (short branch instructions).
static void group_only_relative8_addressing(int opcode)
{
struct result_int_t target;
intval_t offset = 0; // dummy value, to not throw more errors than necessary
struct result_t target;
intval_t offset = 0; // dummy value, to not throw more errors than necessary
ALU_int_result(&target);
typesystem_want_addr(&target);
// FIXME - read pc via function call instead!
if (CPU_state.pc.flags & target.flags & MVALUE_DEFINED) {
if ((target.intval | 0xffff) != 0xffff) {
not_in_bank(target.intval);
if ((target.val.intval | 0xffff) != 0xffff) {
not_in_bank(target.val.intval);
} else {
offset = (target.intval - (CPU_state.pc.intval + 2)) & 0xffff; // clip to 16 bit offset
offset = (target.val.intval - (CPU_state.pc.val.intval + 2)) & 0xffff; // clip to 16 bit offset
// fix sign
if (offset & 0x8000)
offset -= 0x10000;
@ -618,16 +623,17 @@ static void group_only_relative8_addressing(int opcode)
// Mnemonics using only 16bit relative addressing (BRL and PER).
static void group_only_relative16_addressing(int opcode)
{
struct result_int_t target;
intval_t offset = 0; // dummy value, to not throw more errors than necessary
struct result_t target;
intval_t offset = 0; // dummy value, to not throw more errors than necessary
ALU_int_result(&target);
typesystem_want_addr(&target);
// FIXME - read pc via function call instead!
if (CPU_state.pc.flags & target.flags & MVALUE_DEFINED) {
if ((target.intval | 0xffff) != 0xffff) {
not_in_bank(target.intval);
if ((target.val.intval | 0xffff) != 0xffff) {
not_in_bank(target.val.intval);
} else {
offset = (target.intval - (CPU_state.pc.intval + 3)) & 0xffff;
offset = (target.val.intval - (CPU_state.pc.val.intval + 3)) & 0xffff;
// no further checks necessary, 16-bit branches can access whole bank
}
}
@ -638,7 +644,7 @@ static void group_only_relative16_addressing(int opcode)
// set addressing mode bits depending on which opcodes exist, then calculate
// argument size and output both opcode and argument
static void make_command(int force_bit, struct result_int_t *result, unsigned long opcodes)
static void make_command(int force_bit, struct result_t *result, unsigned long opcodes)
{
int addressing_modes = MAYBE______;
@ -651,15 +657,15 @@ static void make_command(int force_bit, struct result_int_t *result, unsigned lo
switch (calc_arg_size(force_bit, result, addressing_modes)) {
case MVALUE_FORCE08:
Output_byte(opcodes & 255);
Output_8b(result->intval);
Output_8b(result->val.intval);
break;
case MVALUE_FORCE16:
Output_byte((opcodes >> 8) & 255);
Output_16b(result->intval);
Output_16b(result->val.intval);
break;
case MVALUE_FORCE24:
Output_byte((opcodes >> 16) & 255);
Output_24b(result->intval);
Output_24b(result->val.intval);
}
}
@ -688,9 +694,9 @@ static unsigned int imm_ops(int *force_bit, unsigned char opcode, int imm_flag)
// plus PEI.
static void group_main(int index, int imm_flag)
{
unsigned long imm_opcodes;
struct result_int_t result;
int force_bit = Input_get_force_bit(); // skips spaces after
unsigned long imm_opcodes;
struct result_t result;
int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) {
case HAM_IMM: // #$ff or #$ffff (depending on accu length)
@ -737,9 +743,9 @@ static void group_main(int index, int imm_flag)
// Various mnemonics with different addressing modes.
static void group_misc(int index, int imm_flag)
{
unsigned long imm_opcodes;
struct result_int_t result;
int force_bit = Input_get_force_bit(); // skips spaces after
unsigned long imm_opcodes;
struct result_t result;
int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) {
case HAM_IMP: // implied addressing
@ -755,7 +761,7 @@ static void group_misc(int index, int imm_flag)
make_command(force_bit, &result, imm_opcodes);
// check whether to warn about 6510's unstable LXA
if ((imm_opcodes == 0xab)
&& ((result.intval & 0xff) != 0x00)
&& ((result.val.intval & 0xff) != 0x00)
&& (result.flags & MVALUE_DEFINED)
&& (CPU_state.type->flags & CPUFLAG_AB_NEEDS_0_ARG))
Throw_warning("Assembling unstable LXA #NONZERO instruction");
@ -796,8 +802,8 @@ static void group_move(int opcode)
// The jump instructions.
static void group_jump(int index)
{
struct result_int_t result;
int force_bit = Input_get_force_bit(); // skips spaces after
struct result_t result;
int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) {
case HAM_ABS: // absolute16 or absolute24
@ -806,7 +812,7 @@ static void group_jump(int index)
case HAM_IND: // ($ffff)
make_command(force_bit, &result, jump_ind[index]);
// check whether to warn about 6502's JMP() bug
if (((result.intval & 0xff) == 0xff)
if (((result.val.intval & 0xff) == 0xff)
&& (result.flags & MVALUE_DEFINED)
&& (CPU_state.type->flags & CPUFLAG_INDIRECTJMPBUGGY))
Throw_warning("Assembling buggy JMP($xxff) instruction");

View File

@ -485,7 +485,7 @@ void Output_passinit(void)
//vcpu stuff:
CPU_state.pc.flags = 0; // not defined yet
CPU_state.pc.intval = 0; // same as output's write_idx on pass init
CPU_state.pc.val.intval = 0; // same as output's write_idx on pass init
CPU_state.add_to_pc = 0; // increase PC by this at end of statement
CPU_state.a_is_long = FALSE; // short accu
CPU_state.xy_are_long = FALSE; // short index regs
@ -554,9 +554,10 @@ void vcpu_set_pc(intval_t new_pc, int segment_flags)
{
intval_t new_offset;
new_offset = (new_pc - CPU_state.pc.intval) & 0xffff;
CPU_state.pc.intval = new_pc;
new_offset = (new_pc - CPU_state.pc.val.intval) & 0xffff;
CPU_state.pc.val.intval = new_pc;
CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined!
CPU_state.pc.addr_refs = 1; // yes, PC counts as address
// now tell output buffer to start a new segment
Output_start_segment(new_offset, segment_flags);
}
@ -614,7 +615,7 @@ void PO_setpc(void)
// get program counter
void vcpu_read_pc(struct result_int_t *target)
void vcpu_read_pc(struct result_t *target)
{
*target = CPU_state.pc;
}
@ -630,6 +631,6 @@ int vcpu_get_statement_size(void)
// adjust program counter (called at end of each statement)
void vcpu_end_statement(void)
{
CPU_state.pc.intval = (CPU_state.pc.intval + CPU_state.add_to_pc) & 0xffff;
CPU_state.pc.val.intval = (CPU_state.pc.val.intval + CPU_state.add_to_pc) & 0xffff;
CPU_state.add_to_pc = 0;
}

View File

@ -19,7 +19,7 @@
// FIXME - move struct definition to .c file and change other .c files' accesses to fn calls
struct vcpu {
const struct cpu_type *type; // current CPU type (default 6502) (FIXME - move out of struct again?)
struct result_int_t pc; // current program counter (pseudo value)
struct result_t pc; // current program counter (pseudo value)
int add_to_pc; // add to PC after statement
int a_is_long;
int xy_are_long;
@ -65,7 +65,7 @@ extern void Output_end_segment(void);
// set program counter to defined value (FIXME - allow undefined!)
extern void vcpu_set_pc(intval_t new_pc, int flags);
// get program counter
extern void vcpu_read_pc(struct result_int_t *target);
extern void vcpu_read_pc(struct result_t *target);
// get size of current statement (until now) - needed for "!bin" verbose output
extern int vcpu_get_statement_size(void);
// adjust program counter (called at end of each statement)

53
src/typesystem.c Normal file
View File

@ -0,0 +1,53 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// Type system stuff
#include "typesystem.h"
#include "config.h"
#include "alu.h"
#include "global.h"
static int in_address_block = FALSE;
static int in_address_statement = FALSE;
// Functions
int typesystem_says_address(void)
{
return in_address_block | in_address_statement;
}
void typesystem_force_address_block(void)
{
int buffer = in_address_block;
in_address_block = TRUE;
Parse_optional_block();
in_address_block = buffer;
}
void typesystem_force_address_statement(int value)
{
in_address_statement = value;
}
void typesystem_want_imm(struct result_t *result)
{
if (!warn_on_type_mismatch)
return;
if (!(result->flags & MVALUE_DEFINED))
return;
if (result->addr_refs != 0)
Throw_warning("Wrong type - expected integer.");
}
void typesystem_want_addr(struct result_t *result)
{
if (!warn_on_type_mismatch)
return;
if (!(result->flags & MVALUE_DEFINED))
return;
if (result->addr_refs != 1)
Throw_warning("Wrong type - expected address.");
}

25
src/typesystem.h Normal file
View File

@ -0,0 +1,25 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// Type system stuff
#ifndef typesystem_H
#define typesystem_H
#include "config.h"
// return whether explicit label definitions should force "address" mode
extern int typesystem_says_address(void);
// parse a block while forcing address mode
extern void typesystem_force_address_block(void);
// force address mode on or off for the next statement
extern void typesystem_force_address_statement(int value);
// warn if result is address instead of integer
extern void typesystem_want_imm(struct result_t *result);
// warn if result is integer instead of address
extern void typesystem_want_addr(struct result_t *result);
#endif