├── cracking └── cracks │ └── nzs │ ├── .gitignore │ ├── gnu │ ├── Makefile │ └── nzs_bootblock.S │ ├── FONT_8x8.BIN │ ├── FONT2_8X8.BIN │ ├── FONT3_8X8.BIN │ ├── gnu_c │ ├── Makefile │ ├── inc │ │ ├── decls.h │ │ ├── types.h │ │ ├── util.h │ │ └── amiga_hw.h │ ├── amiga.ld │ ├── nzs_bootblock.S │ ├── util.c │ └── trainer.c │ ├── phxass │ ├── smakefile │ └── nzs_bootblock.asm │ ├── Makefile │ ├── README │ └── Rules.mk ├── base ├── Makefile ├── font.raw ├── inc │ ├── decls.h │ ├── types.h │ ├── cancellation.h │ ├── m68k.h │ ├── util.h │ └── amiga_hw.h ├── amiga.ld ├── mk_amiga_exe.py ├── cancellation.c ├── Rules.mk ├── entry.S ├── mk_adf.py ├── bootblock.S ├── util.c └── init.S ├── testkit ├── .gitignore ├── AmigaTestKit.info ├── ptplayer │ ├── cda.mod │ ├── spice.mod │ ├── cia.i │ ├── license │ ├── wrapper.c │ └── custom.i ├── README.md ├── build.c ├── Makefile ├── kickmem.c ├── RELEASE_NOTES ├── mfm.S ├── audio.c ├── testkit.h ├── crash.c └── keyboard.c ├── attic ├── trackdisk.zip ├── pc_drive_mods.txt ├── boot_drive_detect.asm ├── crc16_ccitt.S └── file_loader.asm ├── inflate ├── test_assets │ └── XenonIcon.gz ├── .gitignore ├── depacker_entry.S ├── Makefile ├── depacker_main.S ├── test_inflate.S ├── depacker_packed.S └── test_inflate.py ├── .gitignore ├── host_tools ├── Makefile ├── 50-boobip.rules ├── boobip.py ├── hunk_loader.c └── kickconv.c ├── Makefile ├── overscan ├── Makefile └── overscan.c ├── COPYING ├── scripts └── mod_info.py ├── .github └── workflows │ ├── ci.yml │ └── release.yml └── README.md /cracking/cracks/nzs/.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | *.elf 3 | -------------------------------------------------------------------------------- /base/Makefile: -------------------------------------------------------------------------------- 1 | include ../base/Rules.mk 2 | 3 | all: 4 | -------------------------------------------------------------------------------- /testkit/.gitignore: -------------------------------------------------------------------------------- 1 | AmigaTestKit 2 | AmigaTestKit-* 3 | -------------------------------------------------------------------------------- /base/font.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/base/font.raw -------------------------------------------------------------------------------- /attic/trackdisk.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/attic/trackdisk.zip -------------------------------------------------------------------------------- /testkit/AmigaTestKit.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/testkit/AmigaTestKit.info -------------------------------------------------------------------------------- /testkit/ptplayer/cda.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/testkit/ptplayer/cda.mod -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu/Makefile: -------------------------------------------------------------------------------- 1 | include ../Rules.mk 2 | .PHONY: all 3 | all: nzs_bootblock.bin nzs.bin 4 | -------------------------------------------------------------------------------- /testkit/ptplayer/spice.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/testkit/ptplayer/spice.mod -------------------------------------------------------------------------------- /cracking/cracks/nzs/FONT_8x8.BIN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/cracking/cracks/nzs/FONT_8x8.BIN -------------------------------------------------------------------------------- /inflate/test_assets/XenonIcon.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/inflate/test_assets/XenonIcon.gz -------------------------------------------------------------------------------- /cracking/cracks/nzs/FONT2_8X8.BIN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/cracking/cracks/nzs/FONT2_8X8.BIN -------------------------------------------------------------------------------- /cracking/cracks/nzs/FONT3_8X8.BIN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keirf/amiga-stuff/HEAD/cracking/cracks/nzs/FONT3_8X8.BIN -------------------------------------------------------------------------------- /inflate/.gitignore: -------------------------------------------------------------------------------- 1 | /test_inflate 2 | /m68k_emulate 3 | /_test_* 4 | /_pack* 5 | /depacker_entry 6 | /depacker_main 7 | /depacker_packed 8 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/Makefile: -------------------------------------------------------------------------------- 1 | OBJS += nzs_crack.o 2 | OBJS += trainer.o 3 | OBJS += util.o 4 | 5 | include ../Rules.mk 6 | 7 | .PHONY: all 8 | all: nzs_bootblock.bin nzs.bin 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.[oa] 2 | .*.d 3 | *~ 4 | *.adf 5 | *.elf 6 | *.bin 7 | *.hex 8 | *.orig 9 | *.rej 10 | *.exe 11 | *.tmp 12 | *.gz 13 | *.zip 14 | degzip 15 | kickconv 16 | hunk_loader 17 | -------------------------------------------------------------------------------- /host_tools/Makefile: -------------------------------------------------------------------------------- 1 | include ../base/Rules.mk 2 | 3 | TARGETS := hunk_loader kickconv 4 | 5 | all: $(TARGETS) 6 | 7 | %: %.c 8 | $(HOSTCC) $(HOSTCFLAGS) $< -o $@ 9 | 10 | clean:: 11 | $(RM) $(TARGETS) 12 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/phxass/smakefile: -------------------------------------------------------------------------------- 1 | all: nzs.o nzs_bootblock.o 2 | 3 | nzs.o: nzs.asm trainer.asm 4 | phxass noexe nzs.asm 5 | 6 | nzs_bootblock.o: nzs_bootblock.asm 7 | phxass noexe nzs_bootblock.asm 8 | clean: 9 | delete \#?.o \#?.lnk \#?.info 10 | -------------------------------------------------------------------------------- /testkit/README.md: -------------------------------------------------------------------------------- 1 | # Amiga Test Kit: The Amiga system test suite 2 | 3 | ## Structure of the distributed ZIP file 4 | 5 | - **AmigaTestKit.adf** 6 | A bootable disk image of the test suite. 7 | 8 | - **AmigaTestKit** 9 | A version runnable from the CLI or Workbench (with accompanying .info file) 10 | 11 | - **debug/** 12 | Debug symbols for diagnosing problems with the test suite 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include base/Rules.mk 2 | 3 | SUBDIRS := base inflate host_tools overscan testkit inflate 4 | SUBDIRS += cracking/cracks/nzs/gnu cracking/cracks/nzs/gnu_c 5 | 6 | .PHONY: $(SUBDIRS) 7 | 8 | all: $(SUBDIRS) 9 | 10 | overscan testkit: inflate 11 | 12 | $(SUBDIRS): 13 | $(MAKE) -C $@ all 14 | 15 | clean:: 16 | @set -e; for subdir in $(SUBDIRS); do \ 17 | $(MAKE) -C $$subdir clean; \ 18 | done 19 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | SUBDIR := gnu_c 4 | 5 | all: 6 | $(MAKE) -C $(SUBDIR) 7 | $(MAKE) nzs_crack.adf 8 | 9 | nzs_crack.adf: nzs.adf $(SUBDIR)/nzs.bin $(SUBDIR)/nzs_bootblock.bin 10 | cp nzs.adf $@ 11 | adfbb $@ -r$(SUBDIR)/nzs_bootblock.bin 12 | adfwrite $@ $(SUBDIR)/nzs.bin 2 10 -r -f -e46414d45 13 | 14 | clean: 15 | $(MAKE) -C $(SUBDIR) clean 16 | $(RM) nzs_crack.adf 17 | -------------------------------------------------------------------------------- /overscan/Makefile: -------------------------------------------------------------------------------- 1 | OBJS += entry.o 2 | OBJS += util.o 3 | OBJS += overscan.o 4 | 5 | include ../base/Rules.mk 6 | 7 | all: overscan.adf 8 | 9 | overscan.adf: bootblock.bin overscan.bin 10 | $(GZIP) overscan.bin 11 | ../inflate/degzip -H overscan.bin.gz overscan.tmp 12 | xdftool $@ format "Overscan" 13 | $(PYTHON) ../base/mk_adf.py bootblock.bin overscan.tmp $@ 14 | $(RM) overscan.tmp 15 | 16 | clean:: 17 | $(RM) *.adf *.exe *.zip $(NAME) *.tmp *.gz 18 | -------------------------------------------------------------------------------- /testkit/build.c: -------------------------------------------------------------------------------- 1 | /* 2 | * build.c 3 | * 4 | * Definitions refreshed on every build. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #include "testkit.h" 13 | 14 | char build_date[] = __DATE__; 15 | char build_time[] = __TIME__; 16 | char version[] = VER; 17 | -------------------------------------------------------------------------------- /testkit/ptplayer/cia.i: -------------------------------------------------------------------------------- 1 | * 2 | * CIA hardware registers 3 | * 4 | * Written by Frank Wille in 2013. 5 | * 6 | 7 | CIAA equ $bfe001 8 | CIAB equ $bfd000 9 | 10 | ; registers 11 | CIAPRA equ $000 12 | CIAPRB equ $100 13 | CIADDRA equ $200 14 | CIADDRB equ $300 15 | CIATALO equ $400 16 | CIATAHI equ $500 17 | CIATBLO equ $600 18 | CIATBHI equ $700 19 | CIATODLO equ $800 20 | CIATODMID equ $900 21 | CIATODHI equ $a00 22 | CIASDR equ $c00 23 | CIAICR equ $d00 24 | CIACRA equ $e00 25 | CIACRB equ $f00 26 | -------------------------------------------------------------------------------- /host_tools/50-boobip.rules: -------------------------------------------------------------------------------- 1 | # UDEV Rules for BooBip ROM switcher 2 | # 3 | # To install, type this command in a terminal: 4 | # sudo cp 50-boobip.rules /etc/udev/rules.d/. 5 | # 6 | # After this file is installed, physically unplug and reconnect BooBip. 7 | # 8 | ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", \ 9 | ENV{ID_MM_DEVICE_IGNORE}="1" 10 | ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", \ 11 | ENV{MTP_NO_PROBE}="1" 12 | ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", \ 13 | SUBSYSTEMS=="usb", TAG+="uaccess" 14 | ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", \ 15 | KERNEL=="ttyACM*", TAG+="uaccess" 16 | ACTION=="add", \ 17 | ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", \ 18 | SYMLINK+="boobip" 19 | -------------------------------------------------------------------------------- /base/inc/decls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * decls.h 3 | * 4 | * Pull in all other header files in an orderly fashion. Source files include 5 | * only this header, and only once. 6 | * 7 | * Written & released by Keir Fraser 8 | * 9 | * This is free and unencumbered software released into the public domain. 10 | * See the file COPYING for more details, or visit . 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #include "types.h" 17 | #include "util.h" 18 | #include "m68k.h" 19 | #include "amiga_hw.h" 20 | #include "cancellation.h" 21 | 22 | /* 23 | * Local variables: 24 | * mode: C 25 | * c-file-style: "Linux" 26 | * c-basic-offset: 4 27 | * tab-width: 4 28 | * indent-tabs-mode: nil 29 | * End: 30 | */ 31 | -------------------------------------------------------------------------------- /base/inc/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * types.h 3 | * 4 | * Standard types. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | typedef unsigned char uint8_t; 13 | typedef unsigned short uint16_t; 14 | typedef unsigned int uint32_t; 15 | 16 | typedef signed char int8_t; 17 | typedef signed short int16_t; 18 | typedef signed int int32_t; 19 | 20 | typedef char bool_t; 21 | #define TRUE 1 22 | #define FALSE 0 23 | 24 | /* 25 | * Local variables: 26 | * mode: C 27 | * c-file-style: "Linux" 28 | * c-basic-offset: 4 29 | * tab-width: 4 30 | * indent-tabs-mode: nil 31 | * End: 32 | */ 33 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/inc/decls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * decls.h 3 | * 4 | * Pull in all other header files in an orderly fashion. Source files include 5 | * only this header, and only once. 6 | * 7 | * Written & released by Keir Fraser 8 | * 9 | * This is free and unencumbered software released into the public domain. 10 | * See the file COPYING for more details, or visit . 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #include "types.h" 17 | #include "util.h" 18 | #include "amiga_hw.h" 19 | #include "../../../../../base/inc/m68k.h" 20 | 21 | /* 22 | * Local variables: 23 | * mode: C 24 | * c-file-style: "Linux" 25 | * c-basic-offset: 4 26 | * tab-width: 4 27 | * indent-tabs-mode: nil 28 | * End: 29 | */ 30 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/inc/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * types.h 3 | * 4 | * Standard types. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | typedef unsigned char uint8_t; 13 | typedef unsigned short uint16_t; 14 | typedef unsigned int uint32_t; 15 | 16 | typedef signed char int8_t; 17 | typedef signed short int16_t; 18 | typedef signed int int32_t; 19 | 20 | typedef char bool_t; 21 | #define TRUE 1 22 | #define FALSE 0 23 | 24 | /* 25 | * Local variables: 26 | * mode: C 27 | * c-file-style: "Linux" 28 | * c-basic-offset: 4 29 | * tab-width: 4 30 | * indent-tabs-mode: nil 31 | * End: 32 | */ 33 | -------------------------------------------------------------------------------- /base/amiga.ld: -------------------------------------------------------------------------------- 1 | ENTRY(start) 2 | 3 | PHDRS 4 | { 5 | /* Define as RW^X to avoid a linker warning */ 6 | text PT_LOAD FLAGS(6); 7 | } 8 | 9 | SECTIONS 10 | { 11 | SUPER_SP = 0x40000; 12 | USER_SP = 0x3fc00; 13 | HEAP_END = 0x3f000; 14 | . = 0x400; 15 | 16 | .text : { 17 | _start = .; 18 | _stext = .; 19 | *(.text.init) 20 | *(.text*) 21 | *(.rodata*) 22 | . = ALIGN(4); 23 | _etext = .; 24 | } :text 25 | 26 | .data : { 27 | . = ALIGN(4); 28 | _sdat = .; 29 | *(.data) 30 | *(.data*) 31 | . = ALIGN(4); 32 | _edat = .; 33 | } :text 34 | 35 | .bss : { 36 | . = ALIGN(4); 37 | _sbss = .; 38 | *(.bss) 39 | *(.bss*) 40 | . = ALIGN(4); 41 | _ebss = .; 42 | _end = .; 43 | } :text 44 | 45 | /DISCARD/ : { 46 | *(.eh_frame) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /inflate/depacker_entry.S: -------------------------------------------------------------------------------- 1 | /* 2 | * depacker_entry.S 3 | * 4 | * Tiny entry point for self-unpacking executables. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | .text 13 | start: 14 | /* Save all registers and start of the SegList. */ 15 | movem.l d0-d7/a0-a7,-(sp) 16 | lea.l start-4(pc),a0 17 | move.l a0,-(sp) 18 | /* Walk the SegList to find the last segment. */ 19 | 1: move.l (a0),d0 20 | lsl.l #2,d0 21 | jeq 2f 22 | move.l d0,a0 23 | jra 1b 24 | 2: /* Jump to last segment (depacker_main). */ 25 | addq.l #4,a0 26 | jmp (a0) 27 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/amiga.ld: -------------------------------------------------------------------------------- 1 | ENTRY(start) 2 | 3 | PHDRS 4 | { 5 | /* Define as RW^X to avoid a linker warning */ 6 | text PT_LOAD FLAGS(6); 7 | } 8 | 9 | SECTIONS 10 | { 11 | GRAPHICS = 0x20000; 12 | SUPER_SP = 0x80000; 13 | USER_SP = 0x7fc00; 14 | . = 0x7e000; 15 | 16 | .text : { 17 | _start = .; 18 | _stext = .; 19 | *(.text.init) 20 | *(.text*) 21 | *(.rodata*) 22 | . = ALIGN(4); 23 | _etext = .; 24 | } :text 25 | 26 | .data : { 27 | . = ALIGN(4); 28 | _sdat = .; 29 | *(.data) 30 | *(.data*) 31 | . = ALIGN(4); 32 | _edat = .; 33 | } :text 34 | 35 | .bss : { 36 | . = ALIGN(4); 37 | _sbss = .; 38 | *(.bss) 39 | *(.bss*) 40 | . = ALIGN(4); 41 | _ebss = .; 42 | _end = .; 43 | } :text 44 | 45 | /DISCARD/ : { 46 | *(.eh_frame) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/README: -------------------------------------------------------------------------------- 1 | The same crack and trainer is shown here in native PhxAss assembler, 2 | and also in syntax suitable for GNU gcc+binutils. 3 | 4 | Main changes for the GNU toolchain: 5 | 6 | 1. Flags are passed to GNU as to avoid needing to prefix register 7 | names with %, keep branches always PC-relative, and to keep addressing 8 | displacements 16-bit. 9 | 10 | 2. Hex literals are prefixed 0x rather than $. 11 | 12 | 3. Automatic shortening of BRA, Bcc, and BSR instructions requires use 13 | of pseudo-op names JRA, Jcc, JBSR. 14 | 15 | 4. Comments are C-style rather than ; to end-of-line. 16 | 17 | 5. RS.x directives for allocating BSS space do not exist. Fake out an 18 | alternative with CPP plus the .struct directive. 19 | 20 | 6. Use .ascii and .asciz directives for string literals. 21 | 22 | 7. Use CPP in place of equ directives 23 | 24 | Really not very much, and the assembler is less buggy than PhxAss. 25 | -------------------------------------------------------------------------------- /base/mk_amiga_exe.py: -------------------------------------------------------------------------------- 1 | # mk_amiga_exe.py 2 | # 3 | # Convert a raw binary into a simple AmigaDOS executable 4 | # file with one loadable hunk and no relocations 5 | # 6 | # Written & released by Keir Fraser 7 | # 8 | # This is free and unencumbered software released into the public domain. 9 | # See the file COPYING for more details, or visit . 10 | 11 | import struct, sys 12 | 13 | HUNK_CODE = 0x3e9 14 | HUNK_END = 0x3f2 15 | HUNK_HEADER = 0x3f3 16 | 17 | def main(argv): 18 | in_f = open(argv[1], "rb") 19 | out_f = open(argv[2], "wb") 20 | in_dat = in_f.read() 21 | in_len = len(in_dat) 22 | assert (in_len & 3) == 0, "input is not longword padded" 23 | out_f.write(struct.pack(">LLLLLL", HUNK_HEADER, 0, 1, 0, 0, in_len//4)) 24 | out_f.write(struct.pack(">LL", HUNK_CODE, in_len//4)) 25 | out_f.write(in_dat) 26 | out_f.write(struct.pack(">L", HUNK_END)) 27 | 28 | if __name__ == "__main__": 29 | main(sys.argv) 30 | -------------------------------------------------------------------------------- /attic/pc_drive_mods.txt: -------------------------------------------------------------------------------- 1 | 1. Change DS1 to DS0. 2 | 2. Cut pin 2 and pin 34. 3 | 3. Connect pin 2 to DSKCHG (old pin 34). 4 | 4. Connect pin 34 to RDY. 5 | 6 | Finding RDY 7 | ============ 8 | May be jumpered or marked. If not may need to search for it. It may 9 | not exist at all. 10 | 11 | Teac 235HF 12 | ---------- 13 | Many variants, by part nr suffix: 14 | 6291: 80-pin ASIC. ASIC pin 10 15 | 7291: 80-pin ASIC. ASIC pin 10 16 | 7383: 80-pin ASIC. ASIC pin 10 17 | 18 | 8291: 56-pin ASIC. No RDY (checked all ASIC pins) 19 | 20 | A291: 52-pin ASIC. Pad TP4, ASIC pin 41 21 | XXX My test drive is missing RDY, 22 | perhaps I got this one wrong XXX 23 | 24 | Teac 235HG 25 | ---------- 26 | C630: 52-pin ASIC (different to 235HF-A291) 27 | Not fully searched, but no obvious RDY. 28 | 29 | NEC FD1231M/FD1231H 30 | ------------------- 31 | ASIC is marked FDN305. 32 | No RDY signal (checked all ASIC pins). 33 | This will apply to all drives using the same ASIC. 34 | The documented hack to use TP15 for RDY is not fully correct: 35 | - it becomes active too quickly after motor on (0-35ms). 36 | - it temporarily becomes active when removing/inserting disks. 37 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /base/inc/cancellation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cancellation.h 3 | * 4 | * Asynchronously-cancellable function calls. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | /* Opaque to users of this interface. However the struct must be zeroed before 13 | * first use. */ 14 | struct cancellation { 15 | void *sp; 16 | }; 17 | 18 | static inline int cancellation_is_running(struct cancellation *c) 19 | { 20 | return c->sp != NULL; 21 | } 22 | 23 | /* Execute (*fn)(arg) in a wrapped cancellable environment. */ 24 | int call_cancellable_fn(struct cancellation *c, int (*fn)(void *), void *arg); 25 | 26 | /* From IRQ content: stop running fn() and immediately return -1. 27 | * Returns 0 if the fn() either was not running, or was running but is now 28 | * succesfully cancelled. Returns -1 if the fn is running but cannot be 29 | * cancelled by the caller. */ 30 | int cancel_call(struct cancellation *c, struct c_exception_frame *frame); 31 | 32 | /* 33 | * Local variables: 34 | * mode: C 35 | * c-file-style: "Linux" 36 | * c-basic-offset: 4 37 | * tab-width: 4 38 | * indent-tabs-mode: nil 39 | * End: 40 | */ 41 | -------------------------------------------------------------------------------- /testkit/ptplayer/license: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /inflate/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX = m68k-amigaos- 2 | CC = $(PREFIX)gcc 3 | AS = $(PREFIX)as 4 | PYTHON = python3 5 | 6 | CFLAGS += -MMD -MF .$(@F).d 7 | DEPS = .*.d 8 | 9 | CFLAGS += -nostdlib -fno-builtin -I.. 10 | CFLAGS += -Os -m68000 -Wall -Werror -std=gnu99 -msoft-float 11 | #CFLAGS += -msmall-code 12 | #CFLAGS += -DDEBUG 13 | LDFLAGS += $(CFLAGS) -s 14 | AFLAGS += $(CFLAGS) -D__ASSEMBLY__ -Wa,--register-prefix-optional 15 | AFLAGS += -Wa,-l -Wa,--bitwise-or -Wa,--base-size-default-16 16 | AFLAGS += -Wa,--disp-size-default-16 -Wa,--pcrel 17 | 18 | all: depacker degzip 19 | 20 | # Test harness for inflate.S 21 | test_inflate: degzip test_inflate.o 22 | $(CC) -o $@ $@.o $(LDFLAGS) 23 | $(PYTHON) test_inflate.py *.[cSo] *.asm ../cracking/protections/* ../cracking/cracks/nzs/gnu_c/* ../testkit/* test_assets/* 24 | 25 | %.o: %.S 26 | $(CC) -o $@ -c $< $(AFLAGS) 27 | 28 | %.o: %.c 29 | $(CC) -o $@ -c $< $(CFLAGS) 30 | 31 | depacker: depacker_entry depacker_main depacker_packed 32 | 33 | depacker_entry: depacker_entry.o 34 | $(CC) -o $@ $@.o $(LDFLAGS) 35 | 36 | depacker_main: depacker_main.o 37 | $(CC) -o $@ $@.o $(LDFLAGS) 38 | 39 | depacker_packed: depacker_packed.o 40 | $(CC) -o $@ $@.o $(LDFLAGS) 41 | 42 | degzip: degzip_gnu.c 43 | gcc -O2 -Wall -o $@ $^ 44 | 45 | .PHONY: test_inflate depacker 46 | 47 | clean: 48 | $(RM) degzip *.o *~ test_inflate _test_* _pack* 49 | $(RM) depacker_main depacker_entry depacker_packed 50 | -------------------------------------------------------------------------------- /scripts/mod_info.py: -------------------------------------------------------------------------------- 1 | # mod_info.py 2 | # 3 | # Display information about a Protracker module. 4 | # 5 | # Written & released by Keir Fraser 6 | # 7 | # This is free and unencumbered software released into the public domain. 8 | # See the file COPYING for more details, or visit . 9 | 10 | import struct, sys 11 | 12 | with open(sys.argv[1], "rb") as f: 13 | dat = f.read() 14 | dlen = len(dat) 15 | 16 | tname, = struct.unpack("20s", dat[:20]) 17 | print("Name: '%s'" % tname.decode('utf-8')) 18 | dat = dat[20:] 19 | samples_len = 0 20 | for i in range(31): 21 | name, wordlen, finetune, volume, repstart, replen = struct.unpack( 22 | ">22sH2B2H", dat[:30]) 23 | dat = dat[30:] 24 | if wordlen == 0: 25 | continue 26 | samples_len += wordlen*2 27 | print("Sample Data: %u" % samples_len) 28 | 29 | songlen, pad = struct.unpack("2B", dat[:2]) 30 | dat = dat[2:] 31 | #assert pad == 127 32 | assert songlen <= 128 33 | print("Song Length: %u" % songlen) 34 | 35 | patterns = list(struct.unpack("128B", dat[:128])) 36 | dat = dat[128:] 37 | patterns = patterns[:songlen] 38 | nr_patterns = max(patterns)+1 39 | print("Nr Patterns: %u (%u bytes)" % (nr_patterns, nr_patterns*1024)) 40 | 41 | mksig, = struct.unpack("4s", dat[:4]) 42 | dat = dat[4:] 43 | assert mksig == b'M.K.' 44 | 45 | totlen = 1084 + nr_patterns*1024 + samples_len 46 | print("Total Bytes: %u (0x%x)" % (totlen, totlen)) 47 | assert totlen <= dlen 48 | 49 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/Rules.mk: -------------------------------------------------------------------------------- 1 | TOOL_PREFIX = m68k-elf- 2 | CC = $(TOOL_PREFIX)gcc 3 | OBJCOPY = $(TOOL_PREFIX)objcopy 4 | 5 | ifneq ($(VERBOSE),1) 6 | TOOL_PREFIX := @$(TOOL_PREFIX) 7 | endif 8 | 9 | FLAGS = -Os -nostdlib -std=gnu99 -iquote inc 10 | FLAGS += -Wall -Werror -Wno-format -Wdeclaration-after-statement 11 | FLAGS += -Wstrict-prototypes -Wredundant-decls -Wnested-externs 12 | FLAGS += -fno-common -fno-exceptions -fno-strict-aliasing -fomit-frame-pointer 13 | FLAGS += -fno-delete-null-pointer-checks -m68000 -msoft-float 14 | 15 | FLAGS += -MMD -MF .$(@F).d 16 | DEPS = .*.d 17 | 18 | CFLAGS += $(FLAGS) -include decls.h 19 | AFLAGS += $(FLAGS) -D__ASSEMBLY__ -Wa,--register-prefix-optional 20 | AFLAGS += -Wa,-l -Wa,--bitwise-or -Wa,--base-size-default-16 21 | AFLAGS += -Wa,--disp-size-default-16 -Wa,--pcrel 22 | LDFLAGS += $(FLAGS) -Wl,--gc-sections -Tamiga.ld 23 | 24 | .DEFAULT_GOAL := all 25 | 26 | .PHONY: clean 27 | 28 | .SECONDARY: 29 | 30 | %.o: %.c Makefile 31 | @echo CC $@ 32 | $(CC) $(CFLAGS) -c $< -o $@ 33 | 34 | %.o: %.S Makefile 35 | @echo AS $@ 36 | $(CC) $(AFLAGS) -c $< -o $@ 37 | 38 | %.elf: $(OBJS) amiga.ld Makefile 39 | @echo LD $@ 40 | $(CC) $(LDFLAGS) $(OBJS) -o $@ 41 | @chmod a-x $@ 42 | 43 | %.elf: %.o amiga.ld Makefile 44 | @echo LD $@ 45 | $(CC) $(LDFLAGS) $< -o $@ 46 | @chmod a-x $@ 47 | 48 | %.bin: %.o 49 | @echo OBJCOPY $@ 50 | $(OBJCOPY) -O binary $< $@ 51 | @chmod a-x $@ 52 | 53 | %.bin: %.elf 54 | @echo OBJCOPY $@ 55 | $(OBJCOPY) -O binary $< $@ 56 | @chmod a-x $@ 57 | 58 | clean: 59 | $(RM) *~ *.o *.elf *.bin $(DEPS) 60 | 61 | -include $(DEPS) 62 | -------------------------------------------------------------------------------- /attic/boot_drive_detect.asm: -------------------------------------------------------------------------------- 1 | _LVOOpenDevice = -444 2 | _LVOCloseDevice = -450 3 | 4 | INCDIR SOURCES:INCLUDE/ 5 | INCLUDE exec/io.i 6 | INCLUDE devices/trackdisk.i 7 | 8 | 9 | BOOT dc.l "DOS"<<8 10 | dc.l 0 11 | dc.l "STR!" 12 | 13 | 14 | ; find drive which was used to boot the disk and determine 15 | ; which drives are available 16 | bsr.b CheckDrives 17 | 18 | ; d3.w: bit mask for available drives 19 | ; d4.w: boot drive 20 | ; d5.w: number of available drives 21 | 22 | .wait bra.b .wait 23 | 24 | 25 | CheckDrives 26 | move.l a1,a5 27 | 28 | moveq #0,d3 ; bit mask for available drives 29 | moveq #-1,d4 ; boot drive: default: unknown 30 | moveq #0,d5 ; number of available drives 31 | moveq #4-1,d6 ; device number and loop counter 32 | .loop bsr.b OpenTrackdisk 33 | tst.l d0 34 | bne.b .noDevice 35 | 36 | addq.w #1,d5 ; drive available 37 | bset d6,d3 38 | 39 | lea IOStdReq(pc),a1 40 | move.l IO_UNIT(a1),d0 41 | cmp.l IO_UNIT(a5),d0 42 | bne.b .noBootDrive 43 | move.w d6,d4 44 | 45 | .noBootDrive 46 | jsr _LVOCloseDevice(a6) 47 | 48 | 49 | .noDevice 50 | dbf d6,.loop 51 | rts 52 | 53 | 54 | 55 | 56 | 57 | OpenTrackdisk 58 | lea TrackDiskName(pc),a0 59 | lea IOStdReq(pc),a1 60 | 61 | pea port(pc) 62 | move.l (a7)+,ReplyPort-IOStdReq(a1) 63 | 64 | pea ReplyPort(pc) 65 | move.l (a7)+,MN_REPLYPORT(a1) 66 | 67 | move.l d6,d0 68 | moveq #0,d1 ; flags 69 | ;move.l $4.W,a6 70 | jmp _LVOOpenDevice(a6) 71 | 72 | 73 | 74 | IOStdReq ds.b IOTD_SIZE 75 | ReplyPort dc.l 0 76 | 77 | port ds.b 100 78 | 79 | TrackDiskName dc.b "trackdisk.device",0 80 | 81 | ds.b 1024 82 | -------------------------------------------------------------------------------- /testkit/Makefile: -------------------------------------------------------------------------------- 1 | NAME := AmigaTestKit 2 | VER := $(shell git rev-parse --short HEAD) 3 | 4 | OBJS += entry.o 5 | OBJS += cancellation.o 6 | OBJS += util.o 7 | OBJS += build.o 8 | OBJS += crash.o 9 | OBJS += audio.o 10 | OBJS += battclock.o 11 | OBJS += cia.o 12 | OBJS += floppy.o 13 | OBJS += joymouse.o 14 | OBJS += keyboard.o 15 | OBJS += kickmem.o 16 | OBJS += memory.o 17 | OBJS += mfm.o 18 | OBJS += serpar.o 19 | OBJS += testkit.o 20 | OBJS += video.o 21 | OBJS += ptplayer/ptplayer.o 22 | 23 | include ../base/Rules.mk 24 | 25 | # build.o must be refreshed on every build 26 | .PHONY: build.c 27 | 28 | all: $(NAME)-$(VER).zip 29 | 30 | build.o: CFLAGS += -DVER="\"$(VER)\"" 31 | 32 | entry.o: AFLAGS += -DDETECT_MEMORY 33 | 34 | $(NAME)-$(VER).zip: $(NAME).adf $(NAME) $(NAME).info README.md $(NAME).elf 35 | $(RM) -r $(NAME)-$(VER) 36 | mkdir -p $(NAME)-$(VER)/debug 37 | cp $^ RELEASE_NOTES $(NAME)-$(VER) 38 | mv $(NAME)-$(VER)/$(NAME).elf $(NAME)-$(VER)/debug 39 | $(RM) $@ 40 | zip -r $@ $(NAME)-$(VER) 41 | 42 | $(NAME): $(NAME).exe 43 | cp $< $@ 44 | chmod 0755 $@ 45 | 46 | $(NAME).exe: $(NAME).bin 47 | $(PYTHON) ../base/mk_amiga_exe.py $< $@ 48 | $(PYTHON) ../inflate/pack_exe.py $@ $@.tmp 49 | mv $@.tmp $@ 50 | 51 | $(NAME).adf: bootblock.bin $(NAME).bin $(NAME) $(NAME).info 52 | $(GZIP) $(NAME).bin 53 | ../inflate/degzip -H $(NAME).bin.gz $(NAME).bin.tmp 54 | xdftool $@ format "AmigaTestKit $(VER)" 55 | $(PYTHON) ../base/mk_adf.py bootblock.bin $(NAME).bin.tmp $@ 56 | $(RM) $(NAME).bin.tmp 57 | xdftool $@ write $(NAME) + write $(NAME).info 58 | 59 | clean:: 60 | $(RM) *.adf *.exe *.zip $(NAME) *.tmp *.gz 61 | $(RM) -r $(NAME)-* ptplayer/*.o 62 | -------------------------------------------------------------------------------- /testkit/ptplayer/wrapper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ptplayer/wrapper.c 3 | * 4 | * GNU C wrappers around the PT Player routines. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | extern uint8_t _mt_Enable; 13 | 14 | void mt_install_cia(int is_pal); 15 | asm ( 16 | "mt_install_cia:\n" 17 | " move.l %a6,-(%sp) \n" 18 | " lea.l (0xdff000).l,%a6 \n" 19 | " sub.l %a0,%a0 \n" 20 | " move.l 8(%sp),%d0 \n" 21 | " jbsr _mt_install_cia \n" 22 | " move.l (%sp)+,%a6 \n" 23 | " rts \n" 24 | ); 25 | 26 | void mt_init(void *mod, int songpos); 27 | asm ( 28 | "mt_init:\n" 29 | " move.l %a6,-(%sp) \n" 30 | " lea.l (0xdff000).l,%a6 \n" 31 | " move.l 8(%sp),%a0 \n" 32 | " sub.l %a1,%a1 \n" 33 | " move.l 12(%sp),%d0 \n" 34 | " jbsr _mt_init \n" 35 | " move.l (%sp)+,%a6 \n" 36 | " rts \n" 37 | ); 38 | 39 | void mt_end(void); 40 | asm ( 41 | "mt_end:\n" 42 | " move.l %a6,-(%sp) \n" 43 | " lea.l (0xdff000).l,%a6 \n" 44 | " jbsr _mt_end \n" 45 | " move.l (%sp)+,%a6 \n" 46 | " rts \n" 47 | ); 48 | 49 | void mt_remove_cia(void); 50 | asm ( 51 | "mt_remove_cia:\n" 52 | " move.l %a6,-(%sp) \n" 53 | " lea.l (0xdff000).l,%a6 \n" 54 | " jbsr _mt_remove_cia \n" 55 | " move.l (%sp)+,%a6 \n" 56 | " rts \n" 57 | ); 58 | 59 | void mt_disablemask(unsigned int mask); 60 | asm ( 61 | "mt_disablemask:\n" 62 | " move.l %a6,-(%sp) \n" 63 | " lea.l (0xdff000).l,%a6 \n" 64 | " move.l 8(%sp),%d0 \n" 65 | " jbsr _mt_disablemask \n" 66 | " move.l (%sp)+,%a6 \n" 67 | " rts \n" 68 | ); 69 | -------------------------------------------------------------------------------- /base/inc/m68k.h: -------------------------------------------------------------------------------- 1 | /* 2 | * m68k.h 3 | * 4 | * M680x0 processor definitions. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | typedef union { 13 | void *p; 14 | uint32_t x; 15 | } m68k_vector_t; 16 | 17 | struct m68k_vector_table { 18 | m68k_vector_t reset_ssp; 19 | m68k_vector_t reset_pc; 20 | m68k_vector_t bus_error; 21 | m68k_vector_t address_error; 22 | m68k_vector_t illegal_instruction; 23 | m68k_vector_t zero_divide; 24 | m68k_vector_t chk_chk2; 25 | m68k_vector_t trapcc_trapv; 26 | m68k_vector_t privilege_violation; 27 | m68k_vector_t trace; 28 | m68k_vector_t a_line; 29 | m68k_vector_t f_line; 30 | m68k_vector_t _rsvd0[1]; 31 | m68k_vector_t coprocessor_protocol_violation; 32 | m68k_vector_t format_error; 33 | m68k_vector_t uninitialised_interrupt; 34 | m68k_vector_t _rsvd1[8]; 35 | m68k_vector_t spurious_interrupt; 36 | m68k_vector_t level1_autovector; 37 | m68k_vector_t level2_autovector; 38 | m68k_vector_t level3_autovector; 39 | m68k_vector_t level4_autovector; 40 | m68k_vector_t level5_autovector; 41 | m68k_vector_t level6_autovector; 42 | m68k_vector_t level7_autovector; 43 | m68k_vector_t trap[16]; 44 | m68k_vector_t _rsvd2[16]; 45 | m68k_vector_t user_interrupt[16]; 46 | }; 47 | 48 | /* An exception frame for entry to a normal C function (which may clobber 49 | * D0-D1/A0-A1). SR/PC are saved automatically during exception processing. 50 | * There may be other state saved beyond those two registers depending on the 51 | * exception type and CPU model. */ 52 | struct c_exception_frame { 53 | uint32_t d0, d1, a0, a1; 54 | uint16_t sr; 55 | uint32_t pc; 56 | }; 57 | 58 | #define SR_TMASK 0xc000 59 | #define SR_SUPER 0x2000 60 | #define SR_MASTER 0x1000 61 | #define SR_IMASK 0x0700 62 | #define CCR_X 0x10 63 | #define CCR_N 0x08 64 | #define CCR_Z 0x04 65 | #define CCR_V 0x02 66 | #define CCR_C 0x01 67 | -------------------------------------------------------------------------------- /base/cancellation.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cancellation.c 3 | * 4 | * Asynchronously-cancellable function calls. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | asm ( 13 | ".global call_cancellable_fn\n" 14 | "call_cancellable_fn:\n" 15 | " movem.l %d2-%d7/%a2-%a6,-(%sp)\n" /* (SP += 44) */ 16 | " move.l 44+4(%sp),%a0 \n" /* A0 = c */ 17 | " move.l %sp,(%a0) \n" /* c->sp = SP */ 18 | " move.l 44+8(%sp),%a0 \n" /* A0 = fn */ 19 | " move.l 44+12(%sp),-(%sp) \n" /* push arg */ 20 | " jsr (%a0) \n" /* (*fn)(arg) */ 21 | " lea 4(%sp),%sp \n" /* pop arg */ 22 | " move.l 44+4(%sp),%a0 \n" /* A0 = c */ 23 | " move.l #0,(%a0) \n" /* c->sp = NULL */ 24 | "1: movem.l (%sp)+,%d2-%d7/%a2-%a6\n" /* (SP -= 44) */ 25 | " rts \n" 26 | "do_cancel: \n" 27 | " move.l %d0,%sp \n" /* SP = c->sp as saved above */ 28 | " moveq #-1,%d0 \n" /* D0 = return code = -1 */ 29 | " jra 1b \n" 30 | ); 31 | 32 | void do_cancel(void); 33 | 34 | int cancel_call(struct cancellation *c, struct c_exception_frame *frame) 35 | { 36 | if (c->sp == NULL) 37 | return 0; 38 | 39 | /* If the caller is nested in supervisor mode, it cannot cancel. */ 40 | if (frame->sr & SR_SUPER) 41 | return -1; 42 | 43 | /* Modify return frame: Jump to cancellation exit path of 44 | * call_cancellable_fn() with original SP in D0. */ 45 | frame->d0 = (uint32_t)c->sp; 46 | frame->pc = (uint32_t)do_cancel; 47 | frame->sr = 0; /* Clear SR */ 48 | 49 | /* Do this work at most once per invocation of call_cancellable_fn. */ 50 | c->sp = NULL; 51 | 52 | return 0; 53 | } 54 | 55 | /* 56 | * Local variables: 57 | * mode: C 58 | * c-file-style: "Linux" 59 | * c-basic-offset: 4 60 | * tab-width: 4 61 | * indent-tabs-mode: nil 62 | * End: 63 | */ 64 | -------------------------------------------------------------------------------- /base/Rules.mk: -------------------------------------------------------------------------------- 1 | # GNU Make cross-dev build rules 2 | # Tested cross-dev setups (gcc/binutils) (*=recommended): 3 | # 4.9.2/2.24, 5.3.0/2.26, 7.1.0/2.28, 9.3.0/2.34*, 14.2.0/2.43.1 4 | # Target is m68k-elf 5 | 6 | TOOL_PREFIX = m68k-elf- 7 | CC = $(TOOL_PREFIX)gcc 8 | OBJCOPY = $(TOOL_PREFIX)objcopy 9 | PYTHON = python3 10 | GZIP = zopfli --i32 11 | #GZIP = gzip -fk9 12 | 13 | ifneq ($(VERBOSE),1) 14 | TOOL_PREFIX := @$(TOOL_PREFIX) 15 | endif 16 | 17 | # -Ofast produces code approx 50% larger than -Os. 18 | # The relative speed of -Ofast vs -Os has not been benchmarked. 19 | OPT_FLAGS = -Os 20 | #OPT_FLAGS = -Ofast 21 | 22 | FLAGS = $(OPT_FLAGS) -nostdlib -std=gnu99 -iquote ../base/inc -fno-builtin 23 | FLAGS += -Wall -Werror -Wno-format -Wdeclaration-after-statement 24 | FLAGS += -Wstrict-prototypes -Wredundant-decls -Wnested-externs 25 | FLAGS += -fno-common -fno-exceptions -fno-strict-aliasing -fomit-frame-pointer 26 | FLAGS += -fno-delete-null-pointer-checks -m68000 -msoft-float 27 | 28 | FLAGS += -MMD -MF .$(@F).d 29 | DEPS = .*.d 30 | 31 | CFLAGS += $(FLAGS) -include decls.h 32 | AFLAGS += $(FLAGS) -D__ASSEMBLY__ -Wa,--register-prefix-optional 33 | AFLAGS += -Wa,-l -Wa,--bitwise-or -Wa,--base-size-default-16 34 | AFLAGS += -Wa,--disp-size-default-16 -Wa,--pcrel 35 | LDFLAGS += $(FLAGS) -Wl,--gc-sections -T../base/amiga.ld 36 | 37 | HOSTCC = gcc 38 | HOSTCFLAGS = -O2 -Wall -Werror 39 | HOSTCFLAGS += -MMD -MF .$(@F).d 40 | 41 | .DEFAULT_GOAL := all 42 | 43 | .PHONY: all clean 44 | 45 | .SECONDARY: 46 | 47 | %.o: %.c Makefile 48 | @echo CC $@ 49 | $(CC) $(CFLAGS) -c $< -o $@ 50 | 51 | %.o: ../base/%.c Makefile 52 | @echo CC $@ 53 | $(CC) $(CFLAGS) -c $< -o $@ 54 | 55 | %.o: %.S Makefile 56 | @echo AS $@ 57 | $(CC) $(AFLAGS) -c $< -o $@ 58 | 59 | %.o: ../base/%.S Makefile 60 | @echo AS $@ 61 | $(CC) $(AFLAGS) -c $< -o $@ 62 | 63 | %.o: %.asm 64 | @echo VASM $@ 65 | vasmm68k_mot -Felf $< -o $@ 66 | 67 | %.elf: $(OBJS) ../base/amiga.ld Makefile 68 | @echo LD $@ 69 | $(CC) $(LDFLAGS) $(OBJS) -o $@ 70 | @chmod a-x $@ 71 | 72 | %.bin: %.elf 73 | @echo OBJCOPY $@ 74 | $(OBJCOPY) -O binary $< $@ 75 | @chmod a-x $@ 76 | 77 | bootblock.bin: bootblock.o 78 | $(OBJCOPY) -O binary $< $@ 79 | chmod a-x $@ 80 | 81 | clean:: 82 | $(RM) *~ *.o *.elf *.bin $(DEPS) 83 | 84 | -include $(DEPS) 85 | -------------------------------------------------------------------------------- /attic/crc16_ccitt.S: -------------------------------------------------------------------------------- 1 | /* 2 | * crc16_ccitt.S 3 | * 4 | * Table-driven CRC16-CCITT implementation. 5 | * 6 | * Usage: Call crc16_ccitt_gentable to generate the 512-byte lookup table. 7 | * This table can then be passed to crc16_ccitt to perform fast CRC 8 | * calculations. The usual start value for crc_in (d0.w) is 0xFFFF. 9 | * 10 | * Written & released by Keir Fraser 11 | * 12 | * This is free and unencumbered software released into the public domain. 13 | * See the file COPYING for more details, or visit . 14 | */ 15 | 16 | /* a0 = data, a1 = table, d0 = crc_in, d1 = # bytes */ 17 | /* d0 = crc_out, all other regs preserved */ 18 | crc16_ccitt: 19 | movem.l d1-d4/a0/a2,-(sp) 20 | move.b d0,d2 /* d2 = crc.lo */ 21 | lsr.w #8,d0 /* d0 = crc.hi */ 22 | subq.l #1,d1 /* d1.w = count.lo */ 23 | move.l d1,d4 24 | swap d4 /* d4.w = count.hi */ 25 | 1: move.b (a0)+,d3 /* 8 */ 26 | eor.b d3,d0 /* 4 crc.hi ^= *p++ */ 27 | lea (a1,d0.w),a2 /* 12 */ 28 | move.b (a2),d0 /* 8 crc.hi = crc16tab[].hi */ 29 | eor.b d2,d0 /* 4 crc.hi ^= crc.lo */ 30 | move.b 256(a2),d2 /* 12 crc.lo = crc16tab[].lo */ 31 | dbf d1,1b /* 10 */ /* == 58 */ 32 | moveq #-1,d1 /* reset inner loop counter */ 33 | dbf d4,1b /* outer loop on count.hi */ 34 | lsl.w #8,d0 35 | move.b d2,d0 /* d0.w = crc */ 36 | movem.l (sp)+,d1-d4/a0/a2 37 | tst.w d0 /* set CC.Z */ 38 | rts 39 | 40 | /* a1 = table */ 41 | crc16_ccitt_gentable: 42 | movem.l d0-d2/a1,-(sp) 43 | moveq #0,d1 /* d1 = byte */ 44 | moveq #0,d0 /* d0 = crc */ 45 | 1: move.b d1,d0 46 | lsl.w #8,d0 /* d0 = byte << 8 */ 47 | moveq #7,d2 48 | 2: lsl.w #1,d0 49 | jcc 3f 50 | eor.w #0x1021,d0 51 | 3: dbf d2,2b 52 | move.b d0,256(a1) /* crc.lo */ 53 | lsr.w #8,d0 54 | move.b d0,(a1)+ /* crc.hi */ 55 | addq.b #1,d1 56 | jne 1b 57 | movem.l (sp)+,d0-d2/a1 58 | rts 59 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/phxass/nzs_bootblock.asm: -------------------------------------------------------------------------------- 1 | load_off equ $400 2 | load_size equ $1200 3 | 4 | start: 5 | ; Standard DOS bootblock header 6 | dc.b 'D','O','S',0 ; signature 7 | dc.l 0 ; checksum (filled later) 8 | dc.l 880 ; dummy root block index 9 | 10 | ; Save trackdisk ioreq for later use 11 | move.l a1,-(sp) 12 | 13 | ; Allocate chip memory for the data we're loading 14 | move.l #load_size,d0 ; size 15 | moveq #3,d1 ; MEMF_PUBLIC | MEMF_CHIP 16 | jsr -$c6(a6) ; exec.AllocMem 17 | move.l d0,-(sp) 18 | bne .load 19 | add.l #8,sp 20 | moveq #-1,d0 21 | rts 22 | 23 | ; Load data 24 | .load: move.l 4(sp),a1 25 | .retry: move.l (sp),$28(a1) ; io_Data 26 | move.l #load_size,$24(a1) ; io_Length 27 | move.l #load_off,$2c(a1) ; io_Offset 28 | move.w #2,$1c(a1) ; io_Command = CMD_READ 29 | jsr -$1c8(a6) ; exec.DoIO 30 | move.l 4(sp),a1 31 | move.b $1f(a1),d0 ; check io_Error 32 | bne .retry ; ...retry if failed 33 | 34 | ; Decrypt data (xorshift) 35 | move.l (sp),a0 36 | move.l #$46414d45,d0 ; w 37 | move.l #$075bcd15,d2 ; x 38 | move.l #$159a55e5,d3 ; y 39 | move.l #$1f123bb5,d4 ; z 40 | move.w #(load_size/4)-1,d1 41 | .dec: move.l d2,d5 ; t = x 42 | lsl.l #8,d5 43 | lsl.l #3,d5 44 | eor.l d2,d5 ; t = x ^ (x << 1)) 45 | move.l d3,d2 ; x = y 46 | move.l d4,d3 ; y = z 47 | move.l d0,d4 ; z = w 48 | move.l d5,d6 49 | lsr.l #8,d6 50 | eor.l d6,d5 ; t = t ^ (t >> 8) 51 | move.l d0,d6 52 | move.w #0,d6 53 | swap d6 54 | lsr.w #3,d6 ; w >> 19 55 | eor.l d6,d5 56 | eor.l d5,d0 ; w = w ^ (w >> 19) ^ (t ^ (t >> 8)) 57 | eor.l d0,(a0)+ 58 | dbf d1,.dec 59 | 60 | ; We have loaded code from disk: Flush caches if possible 61 | cmp.w #37,$14(a6) ; exec.lib_version >= 37 62 | bmi .done 63 | jsr -$27c(a6) ; exec.CacheClearU 64 | 65 | ; Clean up our stack and jump at what we just loaded 66 | .done: movem.l (sp)+,a0-a1 67 | jmp (a0) 68 | 69 | dc.b "Cracked by KAF June 2011" 70 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu/nzs_bootblock.S: -------------------------------------------------------------------------------- 1 | #define load_off 0x400 2 | #define load_size 0x1200 3 | 4 | start: 5 | /* Standard DOS bootblock header */ 6 | dc.b 'D','O','S',0 /* signature */ 7 | dc.l 0 /* checksum (filled later) */ 8 | dc.l 880 /* dummy root block index */ 9 | 10 | /* Save trackdisk ioreq for later use */ 11 | move.l a1,-(sp) 12 | 13 | /* Allocate chip memory for the data we're loading */ 14 | move.l #load_size,d0 /* size */ 15 | moveq #3,d1 /* MEMF_PUBLIC | MEMF_CHIP */ 16 | jsr -0xc6(a6) /* exec.AllocMem */ 17 | move.l d0,-(sp) 18 | jne .load 19 | add.l #8,sp 20 | moveq #-1,d0 21 | rts 22 | 23 | /* Load data */ 24 | .load: move.l 4(sp),a1 25 | .retry: move.l (sp),0x28(a1) /* io_Data */ 26 | move.l #load_size,0x24(a1) /* io_Length */ 27 | move.l #load_off,0x2c(a1) /* io_Offset */ 28 | move.w #2,0x1c(a1) /* io_Command = CMD_READ */ 29 | jsr -0x1c8(a6) /* exec.DoIO */ 30 | move.l 4(sp),a1 31 | move.b 0x1f(a1),d0 /* check io_Error */ 32 | jne .retry /* ...retry if failed */ 33 | 34 | /* Decrypt data (xorshift) */ 35 | move.l (sp),a0 36 | move.l #0x46414d45,d0 /* w */ 37 | move.l #0x075bcd15,d2 /* x */ 38 | move.l #0x159a55e5,d3 /* y */ 39 | move.l #0x1f123bb5,d4 /* z */ 40 | move.w #(load_size/4)-1,d1 41 | .dec: move.l d2,d5 /* t = x */ 42 | lsl.l #8,d5 43 | lsl.l #3,d5 44 | eor.l d2,d5 /* t = x ^ (x << 1)) */ 45 | move.l d3,d2 /* x = y */ 46 | move.l d4,d3 /* y = z */ 47 | move.l d0,d4 /* z = w */ 48 | move.l d5,d6 49 | lsr.l #8,d6 50 | eor.l d6,d5 /* t = t ^ (t >> 8) */ 51 | move.l d0,d6 52 | move.w #0,d6 53 | swap d6 54 | lsr.w #3,d6 /* w >> 19 */ 55 | eor.l d6,d5 56 | eor.l d5,d0 /* w = w ^ (w >> 19) ^ (t ^ (t >> 8)) */ 57 | eor.l d0,(a0)+ 58 | dbf d1,.dec 59 | 60 | /* We have loaded code from disk: Flush caches if possible */ 61 | cmp.w #37,0x14(a6) /* exec.lib_version >= 37 */ 62 | jmi .done 63 | jsr -0x27c(a6) /* exec.CacheClearU */ 64 | 65 | /* Clean up our stack and jump at what we just loaded */ 66 | .done: movem.l (sp)+,a0-a1 67 | jmp (a0) 68 | 69 | .ascii "Cracked by KAF June 2011" 70 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/nzs_bootblock.S: -------------------------------------------------------------------------------- 1 | #define load_off 0x400 2 | #define load_size 0x1200 3 | 4 | start: 5 | /* Standard DOS bootblock header */ 6 | dc.b 'D','O','S',0 /* signature */ 7 | dc.l 0 /* checksum (filled later) */ 8 | dc.l 880 /* dummy root block index */ 9 | 10 | /* Save trackdisk ioreq for later use */ 11 | move.l a1,-(sp) 12 | 13 | /* Allocate chip memory for the data we're loading */ 14 | move.l #load_size,d0 /* size */ 15 | moveq #3,d1 /* MEMF_PUBLIC | MEMF_CHIP */ 16 | jsr -0xc6(a6) /* exec.AllocMem */ 17 | move.l d0,-(sp) 18 | jne .load 19 | add.l #8,sp 20 | moveq #-1,d0 21 | rts 22 | 23 | /* Load data */ 24 | .load: move.l 4(sp),a1 25 | .retry: move.l (sp),0x28(a1) /* io_Data */ 26 | move.l #load_size,0x24(a1) /* io_Length */ 27 | move.l #load_off,0x2c(a1) /* io_Offset */ 28 | move.w #2,0x1c(a1) /* io_Command = CMD_READ */ 29 | jsr -0x1c8(a6) /* exec.DoIO */ 30 | move.l 4(sp),a1 31 | move.b 0x1f(a1),d0 /* check io_Error */ 32 | jne .retry /* ...retry if failed */ 33 | 34 | /* Decrypt data (xorshift) */ 35 | move.l (sp),a0 36 | move.l #0x46414d45,d0 /* w */ 37 | move.l #0x075bcd15,d2 /* x */ 38 | move.l #0x159a55e5,d3 /* y */ 39 | move.l #0x1f123bb5,d4 /* z */ 40 | move.w #(load_size/4)-1,d1 41 | .dec: move.l d2,d5 /* t = x */ 42 | lsl.l #8,d5 43 | lsl.l #3,d5 44 | eor.l d2,d5 /* t = x ^ (x << 1)) */ 45 | move.l d3,d2 /* x = y */ 46 | move.l d4,d3 /* y = z */ 47 | move.l d0,d4 /* z = w */ 48 | move.l d5,d6 49 | lsr.l #8,d6 50 | eor.l d6,d5 /* t = t ^ (t >> 8) */ 51 | move.l d0,d6 52 | move.w #0,d6 53 | swap d6 54 | lsr.w #3,d6 /* w >> 19 */ 55 | eor.l d6,d5 56 | eor.l d5,d0 /* w = w ^ (w >> 19) ^ (t ^ (t >> 8)) */ 57 | eor.l d0,(a0)+ 58 | dbf d1,.dec 59 | 60 | /* We have loaded code from disk: Flush caches if possible */ 61 | cmp.w #37,0x14(a6) /* exec.lib_version >= 37 */ 62 | jcs .done 63 | jsr -0x27c(a6) /* exec.CacheClearU */ 64 | 65 | /* Clean up our stack and jump at what we just loaded */ 66 | .done: movem.l (sp)+,a0-a1 67 | jmp (a0) 68 | 69 | .ascii "Cracked by KAF June 2011" 70 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * util.c 3 | * 4 | * General-purpose utility functions. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | int vsprintf(char *str, const char *format, va_list ap) 13 | { 14 | unsigned int x; 15 | short width; 16 | char c, *p = str, tmp[12], *q; 17 | 18 | while ((c = *format++) != '\0') { 19 | if (c != '%') { 20 | *p++ = c; 21 | continue; 22 | } 23 | 24 | width = 0; 25 | more: 26 | switch (c = *format++) { 27 | case '1'...'9': 28 | width = c-'0'; 29 | while (((c = *format) >= '0') && (c <= '9')) { 30 | width = width*10 + c-'0'; 31 | format++; 32 | } 33 | goto more; 34 | case 'd': 35 | case 'u': 36 | break; 37 | case 's': 38 | q = va_arg(ap, char *); 39 | while ((c = *q++) != '\0') { 40 | *p++ = c; 41 | width--; 42 | } 43 | while (width-- > 0) 44 | *p++ = '.'; 45 | continue; 46 | case 'c': 47 | c = va_arg(ap, unsigned int); 48 | default: 49 | *p++ = c; 50 | continue; 51 | } 52 | 53 | x = va_arg(ap, unsigned int); 54 | 55 | if (x == 0) { 56 | q = tmp; 57 | *q++ = '0'; 58 | } else { 59 | for (q = tmp; x; q++) 60 | *q = '0' + do_div(x, 10); 61 | } 62 | while (width-- > (q-tmp)) 63 | *p++ = ' '; 64 | while (q != tmp) 65 | *p++ = *--q; 66 | }; 67 | 68 | *p = '\0'; 69 | 70 | return p - str; 71 | } 72 | 73 | int sprintf(char *str, const char *format, ...) 74 | { 75 | va_list ap; 76 | int n; 77 | 78 | va_start(ap, format); 79 | n = vsprintf(str, format, ap); 80 | va_end(ap); 81 | 82 | return n; 83 | } 84 | 85 | void *memset(void *s, int c, size_t n) 86 | { 87 | char *p = s; 88 | while (n--) 89 | *p++ = c; 90 | return s; 91 | } 92 | 93 | void *memcpy(void *dest, const void *src, size_t n) 94 | { 95 | char *p = dest; 96 | const char *q = src; 97 | while (n--) 98 | *p++ = *q++; 99 | return dest; 100 | } 101 | 102 | /* 103 | * Local variables: 104 | * mode: C 105 | * c-file-style: "Linux" 106 | * c-basic-offset: 4 107 | * tab-width: 4 108 | * indent-tabs-mode: nil 109 | * End: 110 | */ 111 | -------------------------------------------------------------------------------- /inflate/depacker_main.S: -------------------------------------------------------------------------------- 1 | /* 2 | * depacker_main.S 3 | * 4 | * Main depacker/loader self-unpacking executables. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | /* LibBase offsets */ 13 | #define LibBase_Version 20 14 | 15 | /* Exec library calls */ 16 | #define Exec_CacheClearU -0x27c 17 | 18 | .text 19 | start: 20 | /* Decompress segment/reloc info in this segment. */ 21 | lea.l sizes(pc),a0 22 | move.l (a0)+,d0 /* d0 = stream_bytes */ 23 | move.l a0,a4 /* a4 = buffer_start */ 24 | move.l a0,a2 /* a2 = buffer_start */ 25 | jeq skip_this_seg /* zero -> not compressed */ 26 | add.l d0,a0 /* a0 = stream_end */ 27 | lea.l start-8(pc),a5 28 | add.l (a5),a5 /* a5 = buffer_end */ 29 | 1: move.l -(a0),-(a5) 30 | subq.l #4,d0 31 | jne 1b 32 | jbsr inflate 33 | skip_this_seg: 34 | 35 | /* Decompress all other segments, first to last. 36 | * a2 = stream_len[seg] */ 37 | move.l (sp),a3 /* a3 = SegList */ 38 | unpack_next_seg: 39 | lea.l 4(a3),a4 /* a4 = buffer_start */ 40 | move.l (a2)+,d0 /* d0 = stream_bytes */ 41 | jeq skip_seg /* zero -> not compressed */ 42 | lea.l (a4,d0.l),a0 /* a0 = stream_end */ 43 | lea.l -8(a4),a5 44 | add.l (a5),a5 /* a5 = buffer_end */ 45 | move.l a5,a1 /* a1 = buffer_end */ 46 | lsr.l #2,d0 47 | cmp.l (sp),a3 /* First segment?... */ 48 | jne 1f 49 | subq.l #6,d0 /* ...Then clip depacker_entry (24 bytes) */ 50 | 1: move.l -(a0),-(a5) 51 | subq.l #1,d0 52 | jne 1b 53 | jbsr inflate 54 | /* Fill remainder of segment allocation with zeroes. */ 55 | cmp.l a4,a1 56 | jeq skip_seg 57 | 1: move.l d0,(a4)+ 58 | cmp.l a4,a1 59 | jne 1b 60 | skip_seg: 61 | move.l (a3),d0 62 | lsl.l #2,d0 63 | move.l d0,a3 /* a3 = next Segment */ 64 | jne unpack_next_seg 65 | 66 | /* Remainder of the loader is packed up with the reloc info. 67 | * Flush caches if possible, then jump at the depacked loader. */ 68 | move.l 4.w,a6 69 | cmp.w #37,LibBase_Version(a6) /* exec.lib_version >= 37? */ 70 | jcs 1f 71 | jsr Exec_CacheClearU(a6) 72 | 1: jmp (a2) 73 | 74 | #define SAVE_RESTORE_REGS d0/a1-a3 75 | #include "inflate.S" 76 | 77 | .balign 4 78 | sizes: 79 | -------------------------------------------------------------------------------- /host_tools/boobip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # boobip.py 4 | # 5 | # Control script for Chris Morley's BooBip ROM switcher. 6 | # Notes: 7 | # Reset is via SP: Connect the SP pad to system /RESET line. 8 | # New adapters should be initialised once only with the 'init' command. 9 | # 10 | # Written & released by Keir Fraser 11 | # 12 | # This is free and unencumbered software released into the public domain. 13 | # See the file COPYING for more details, or visit . 14 | 15 | import serial, sys, time 16 | 17 | def ser_open(): 18 | try: 19 | ser = serial.Serial('/dev/boobip') 20 | except serial.SerialException as e: 21 | print(e) 22 | sys.exit(1) 23 | ser.reset_input_buffer() 24 | return ser 25 | 26 | def print_help(argv): 27 | print('Usage: %s CMD [OPTS]...' % argv[0]) 28 | print('Commands:') 29 | print(' h : Print this message') 30 | print(' r : Reset the host') 31 | print(' s 0-3 : Reset and Switch to selected ROM') 32 | print(' p 0-3 BIN : Reset, Program and Switch to selected ROM') 33 | print(' init : Initialise a new BooBip switcher (only needed once)') 34 | sys.exit(1) 35 | 36 | def rst(ser, pre=b'', post=b''): 37 | ser.write(b'9l' + pre) # SP low 38 | time.sleep(0.5) 39 | ser.write(post + b'9z') # SP hi-z 40 | 41 | def reset(argv): 42 | if len(argv) != 2: 43 | print_help(argv) 44 | rst(ser_open()) 45 | 46 | def switch(argv): 47 | if len(argv) != 3: 48 | print_help(argv) 49 | bank = int(argv[2]) 50 | ser = ser_open() 51 | # 'wN': Switch to ROM #N 52 | rst(ser, post = b'w%d' % bank) 53 | 54 | def program(argv): 55 | if len(argv) != 4: 56 | print_help(argv) 57 | bank, image = int(argv[2]), argv[3] 58 | ser = ser_open() 59 | # 'pN5y': program #N with 512kB data requiring byteswap 60 | # Do this under reset. No need for extra delay as in rst(). 61 | ser.write(b'9lp%d5y' % bank) 62 | with open(image, 'rb') as f: 63 | ser.write(f.read()) 64 | ser.write(b'w%d9z' % bank) 65 | 66 | def init(argv): 67 | if len(argv) != 2: 68 | print_help(argv) 69 | ser = ser_open() 70 | # 'o' & '^': Enter & Exit the option menu 71 | # 'p1m': 27C400, master 72 | # 'wn': disable wireless ROM switch 73 | # 'ln': disable LED 74 | # 'c': commit to Flash 75 | ser.write(b'op1mwnlnc^') 76 | rst(ser) 77 | 78 | def main(argv): 79 | if len(argv) < 2: 80 | print_help(argv) 81 | cmd = argv[1] 82 | if cmd == 'r': 83 | reset(argv) 84 | elif cmd == 's': 85 | switch(argv) 86 | elif cmd == 'p': 87 | program(argv) 88 | elif cmd == 'init': 89 | init(argv) 90 | else: 91 | print_help(argv) 92 | 93 | if __name__ == "__main__": 94 | main(sys.argv) 95 | 96 | # Local variables: 97 | # python-indent: 4 98 | # End: 99 | -------------------------------------------------------------------------------- /testkit/kickmem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kickmem.c 3 | * 4 | * Kickstart detection. 5 | * 6 | * Written & released by Rene F. 7 | * Modified by Keir Fraser 8 | * 9 | * This is free and unencumbered software released into the public domain. 10 | * See the file COPYING for more details, or visit . 11 | */ 12 | 13 | #include "testkit.h" 14 | 15 | static struct amiga_kickstart { 16 | uint16_t magic; /* 0x1111, 1114, .... */ 17 | uint16_t entry_jmp; /* 0x4ef9 */ 18 | uint32_t entry_adr; 19 | uint16_t reserved1; /* 0x0000 */ 20 | uint16_t reserved2; /* 0xffff */ 21 | uint16_t ver_major; 22 | uint16_t ver_minor; 23 | } * const kickmem = (struct amiga_kickstart *)0xf80000; 24 | 25 | /* Kickstart versions according to https://de.wikipedia.org/wiki/Kickstart */ 26 | static struct kick_ver { 27 | uint16_t ver_major, ver_minor; 28 | char str[9]; 29 | } kickstart_versions[] = { 30 | { 30, -1, "1.0" }, 31 | { 31, -1, "1.1 NTSC" }, 32 | { 32, -1, "1.1 PAL" }, 33 | { 33, -1, "1.2" }, 34 | { 34, -1, "1.3" }, 35 | { 35, -1, "1.3 2024" }, 36 | { 36, -1, "1.4 beta" }, 37 | { 37, 175, "2.04" }, 38 | { 37, 299, "2.05" }, 39 | { 37, 300, "2.05" }, 40 | { 37, 350, "2.05" }, 41 | { 37, -1, "2.0x" }, 42 | { 39, -1, "3.0" }, 43 | { 40, -1, "3.1" }, 44 | { 42, -1, "3.2" }, 45 | { 43, -1, "3.1patch" }, 46 | { 44, -1, "3.5" }, 47 | { 45, -1, "3.9" }, 48 | { 46, -1, "3.1.4" }, 49 | { 47, 102, "3.2.1" }, 50 | { 47, 111, "3.2.2" }, 51 | { 47, -1, "3.2" }, 52 | { 50, -1, "MorphOS1" }, 53 | { 51, -1, "MorphOS2" }, 54 | { 52, -1, "4.0" }, 55 | { 53, -1, "4.1" } 56 | }; 57 | 58 | const char *get_kick_string(void) 59 | { 60 | static char kick_string[32]; 61 | 62 | struct kick_ver *kick_ver; 63 | int i; 64 | 65 | /* Already detected Kickstart? Just return it again. */ 66 | if (*kick_string != '\0') 67 | return kick_string; 68 | 69 | /* Basic sanity check for what a Kickstart ROM header looks like. */ 70 | if ((kickmem->reserved1 != 0x0000) 71 | || (kickmem->reserved2 != 0xffff) 72 | || (kickmem->ver_major > 99) 73 | || (kickmem->ver_minor > 999)) { 74 | strcpy(kick_string, "Kickstart Not Found"); 75 | return kick_string; 76 | } 77 | 78 | for (i = 0; i < ARRAY_SIZE(kickstart_versions); i++ ) 79 | { 80 | kick_ver = &kickstart_versions[i]; 81 | if ((kick_ver->ver_major == kickmem->ver_major) 82 | && ((kick_ver->ver_minor == kickmem->ver_minor) 83 | || (kick_ver->ver_minor == 0xffffu))) 84 | goto found; 85 | } 86 | 87 | sprintf(kick_string, "Unknown Kickstart (%u.%u)", 88 | kickmem->ver_major, kickmem->ver_minor); 89 | return kick_string; 90 | 91 | found: 92 | sprintf(kick_string, "Kickstart %s (%u.%u)", 93 | kick_ver->str, kickmem->ver_major, kickmem->ver_minor); 94 | return kick_string; 95 | } 96 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | env: 8 | BINUTILS_RELEASE: 2.34 9 | GCC_RELEASE: 9.3.0 10 | runs-on: ubuntu-22.04 11 | 12 | steps: 13 | 14 | - uses: actions/checkout@v3 15 | 16 | - name: Set environment variables 17 | id: vars 18 | run: | 19 | echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 20 | 21 | - name: Dependency packages 22 | run: | 23 | sudo apt update 24 | sudo apt install -y autoconf bison build-essential flex gettext git lhasa libgmp-dev libmpc-dev libmpfr-dev ncurses-dev rsync texinfo wget tzdata zopfli python3-pip 25 | python3 -m pip install --user -U pip setuptools 26 | python3 -m pip install --user crcmod cython 27 | python3 -m pip install --user -U git+https://github.com/cnvogelg/amitools.git 28 | 29 | - name: Cache toolchain 30 | id: cache-toolchain 31 | uses: actions/cache@v3 32 | with: 33 | path: ~/cross 34 | key: ${{ runner.os }}-${{ env.BINUTILS_RELEASE }}-${{ env.GCC_RELEASE }}-4 35 | 36 | - name: Build toolchain 37 | if: steps.cache-toolchain.outputs.cache-hit != 'true' 38 | env: 39 | MAKE_OPTS: -j4 40 | MAKE_DIR: cross 41 | run: | 42 | git config --global pull.rebase false 43 | export MDIR=$HOME/${MAKE_DIR} 44 | mkdir -p $MDIR/bin 45 | export PATH=$PATH:$MDIR 46 | mkdir ~/_tc && cd ~/_tc 47 | wget https://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_RELEASE}.tar.xz 48 | wget https://ftp.gnu.org/gnu/gcc/gcc-${GCC_RELEASE}/gcc-${GCC_RELEASE}.tar.xz 49 | tar xf binutils-${BINUTILS_RELEASE}.tar.xz 50 | tar xf gcc-${GCC_RELEASE}.tar.xz 51 | cd binutils-${BINUTILS_RELEASE} 52 | ./configure --prefix=$MDIR --target=m68k-elf 53 | make ${MAKE_OPTS} 54 | make install 55 | cd ../gcc-${GCC_RELEASE} 56 | ./contrib/download_prerequisites 57 | mkdir ../gcc-build && cd ../gcc-build 58 | ../gcc-${GCC_RELEASE}/configure --prefix=$MDIR --target=m68k-elf --enable-languages=c --disable-libssp 59 | make ${MAKE_OPTS} 60 | make install 61 | cd .. 62 | git clone https://github.com/bebbo/amiga-gcc.git 63 | cd amiga-gcc 64 | make update 65 | make all ${MAKE_OPTS} PREFIX=$MDIR 66 | 67 | - name: Build dist 68 | run: | 69 | export PATH=$PATH:~/cross/bin 70 | export VER=${{ steps.vars.outputs.sha_short }} 71 | make all 72 | cd testkit 73 | make clean && make -j4 all VER=$VER 74 | rm AmigaTestKit-$VER/RELEASE_NOTES 75 | git rev-parse HEAD >AmigaTestKit-$VER/COMMIT 76 | cd .. 77 | mkdir -p _cidist/amiga-stuff.ci.$VER 78 | mv testkit/AmigaTestKit-$VER _cidist/amiga-stuff.ci.$VER 79 | cp -a host_tools inflate _cidist/amiga-stuff.ci.$VER 80 | 81 | - name: Upload artifacts 82 | uses: actions/upload-artifact@v4 83 | with: 84 | name: amiga-stuff.ci.${{ steps.vars.outputs.sha_short }} 85 | path: _cidist 86 | -------------------------------------------------------------------------------- /inflate/test_inflate.S: -------------------------------------------------------------------------------- 1 | /* 2 | * test_inflate.S 3 | * 4 | * Test harness for inflate.S 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | .text 13 | start: 14 | // Calculate input parameters: 15 | // a0 = stream_start (start of DEFLATE stream); 16 | // a1 = buffer_start (start of decompression buffer); 17 | // d0.l = stream_len (DEFLATE stream length in bytes); 18 | // d1.l = original_len (unpacked file length); 19 | // d2.l = leeway / security #bytes 20 | // On stack: original_len, header_crc 21 | lea input(pc),a0 22 | move.l a0,a1 // a1 = buffer_start 23 | movem.l (a0)+,d0-d2 // a0 = stream_start, d0=in_len, d1=out_len 24 | swap d2 25 | movem.l d1-d2,-(sp) // save original_len and header_crc.w 26 | clr.w d2 27 | swap d2 // d2.l = leeway 28 | sub.l #12+2,d0 // d0.l = stream_len = DEFLATE stream length 29 | // Calculate a1 = End of output buffer (longword aligned) 30 | add.l d1,d2 // d2 = original_len + leeway 31 | moveq #0,d1 32 | move.b d0,d1 33 | neg.b d1 34 | and.b #3,d1 // d1.l = -stream_len & 3 (= input padding) 35 | add.l d1,d2 // d2 += input padding (extra leeway) 36 | addq.l #3,d2 37 | and.b #0xfc,d2 // d2 = buffer_size, rounded up to a longword 38 | add.l d2,a1 // a1 = buffer_end 39 | // Calculate d0 = DEFLATE stream length, rounded to longwoprd multiple 40 | addq.l #3,d0 41 | and.b #0xfc,d0 42 | // Calculate a0 = End of DEFLATE stream (longword aligned) 43 | add.l d0,a0 // a0 = stream_end 44 | // Output buffer must include the full DEFLATE stream 45 | cmp.l a0,a1 // stream_end > buffer_end? 46 | jcc 1f 47 | move.l a0,a1 // buffer_end = stream_end 48 | 1: // Compute CRC table 49 | move.l a1,-(sp) // Save crctable 50 | jbsr crc16_ccitt_gentable 51 | // Copy DEFLATE stream to end of output buffer 52 | lsr.l #2,d0 // d0 = DEFLATE stream length in longwords 53 | 1: move.l -(a0),-(a1) 54 | subq.l #1,d0 55 | jne 1b 56 | // INFLATE 57 | move.l a1,a5 // a5 = input stream 58 | lea input(pc),a4 // a4 = output buffer 59 | jbsr inflate 60 | // Compute CRC over unpacked data 61 | move.l (sp)+,a1 // a1 = crctable 62 | move.l a4,a0 // a0 = data 63 | movem.l (sp)+,d1-d2 // d1.l = original_len; d2.w = header_crc 64 | moveq #-1,d0 // d0.w = in_crc 65 | jbsr crc16_ccitt 66 | // CRC correct? 67 | cmp.w d0,d2 68 | rts // d0.w and d2.w should match! 69 | 70 | #include "../attic/crc16_ccitt.S" 71 | #include "inflate.S" 72 | 73 | .balign 4 74 | input: 75 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | tags: 4 | - 'testkit-v*.*' 5 | 6 | name: Release 7 | 8 | jobs: 9 | build: 10 | env: 11 | BINUTILS_RELEASE: 2.34 12 | GCC_RELEASE: 9.3.0 13 | runs-on: ubuntu-22.04 14 | 15 | steps: 16 | 17 | - uses: actions/checkout@v3 18 | 19 | - name: Set environment variables 20 | id: vars 21 | run: | 22 | echo "ver=$(echo ${{ github.ref }} | sed -e's#.*testkit-v##')" >> $GITHUB_OUTPUT 23 | 24 | - name: Dependency packages 25 | run: | 26 | sudo apt update 27 | sudo apt install -y autoconf bison build-essential flex gettext git lhasa libgmp-dev libmpc-dev libmpfr-dev ncurses-dev rsync texinfo wget tzdata zopfli python3-pip 28 | python3 -m pip install --user -U pip setuptools 29 | python3 -m pip install --user crcmod cython 30 | python3 -m pip install --user -U git+https://github.com/cnvogelg/amitools.git 31 | 32 | - name: Cache toolchain 33 | id: cache-toolchain 34 | uses: actions/cache@v3 35 | with: 36 | path: ~/cross 37 | key: ${{ runner.os }}-${{ env.BINUTILS_RELEASE }}-${{ env.GCC_RELEASE }}-4 38 | 39 | - name: Build toolchain 40 | if: steps.cache-toolchain.outputs.cache-hit != 'true' 41 | env: 42 | MAKE_OPTS: -j4 43 | MAKE_DIR: cross 44 | run: | 45 | git config --global pull.rebase false 46 | export MDIR=$HOME/${MAKE_DIR} 47 | mkdir -p $MDIR/bin 48 | export PATH=$PATH:$MDIR 49 | mkdir ~/_tc && cd ~/_tc 50 | wget https://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_RELEASE}.tar.xz 51 | wget https://ftp.gnu.org/gnu/gcc/gcc-${GCC_RELEASE}/gcc-${GCC_RELEASE}.tar.xz 52 | tar xf binutils-${BINUTILS_RELEASE}.tar.xz 53 | tar xf gcc-${GCC_RELEASE}.tar.xz 54 | cd binutils-${BINUTILS_RELEASE} 55 | ./configure --prefix=$MDIR --target=m68k-elf 56 | make ${MAKE_OPTS} 57 | make install 58 | cd ../gcc-${GCC_RELEASE} 59 | ./contrib/download_prerequisites 60 | mkdir ../gcc-build && cd ../gcc-build 61 | ../gcc-${GCC_RELEASE}/configure --prefix=$MDIR --target=m68k-elf --enable-languages=c --disable-libssp 62 | make ${MAKE_OPTS} 63 | make install 64 | cd .. 65 | git clone https://github.com/bebbo/amiga-gcc.git 66 | cd amiga-gcc 67 | make update 68 | make all ${MAKE_OPTS} PREFIX=$MDIR 69 | 70 | - name: Build dist 71 | run: | 72 | export PATH=$PATH:~/cross/bin 73 | export VER=${{ steps.vars.outputs.ver }} 74 | make all 75 | cd testkit 76 | make clean && make -j4 all VER=$VER 77 | 78 | - name: Create Release 79 | id: create_release 80 | uses: ncipollo/release-action@v1 81 | with: 82 | tag: ${{ github.ref }} 83 | token: ${{ secrets.GITHUB_TOKEN }} 84 | name: "Amiga Test Kit ${{ steps.vars.outputs.ver }}" 85 | body: "[**Download Amiga Test Kit ${{ steps.vars.outputs.ver }}**](https://github.com/keirf/amiga-stuff/releases/download/testkit-v${{ steps.vars.outputs.ver }}/AmigaTestKit-${{ steps.vars.outputs.ver }}.zip)" 86 | draft: false 87 | prerelease: false 88 | artifacts: testkit/AmigaTestKit-${{ steps.vars.outputs.ver }}.zip 89 | artifactContentType: application/zip 90 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/inc/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * util.h 3 | * 4 | * General utility functions and definitions. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #if __GNUC__ < 3 13 | #define attribute_used __attribute__((unused)) 14 | #define likely(x) x 15 | #define unlikely(x) x 16 | #else 17 | #define attribute_used __attribute__((used)) 18 | #define likely(x) __builtin_expect((x),1) 19 | #define unlikely(x) __builtin_expect((x),0) 20 | #endif 21 | 22 | #define barrier() asm volatile("" ::: "memory") 23 | 24 | #ifndef offsetof 25 | #define offsetof(a,b) __builtin_offsetof(a,b) 26 | #endif 27 | #define container_of(ptr, type, member) ({ \ 28 | typeof( ((type *)0)->member ) *__mptr = (ptr); \ 29 | (type *)( (char *)__mptr - offsetof(type,member) );}) 30 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 31 | 32 | #define min(x,y) ({ \ 33 | const typeof(x) _x = (x); \ 34 | const typeof(y) _y = (y); \ 35 | (void) (&_x == &_y); \ 36 | _x < _y ? _x : _y; }) 37 | 38 | #define max(x,y) ({ \ 39 | const typeof(x) _x = (x); \ 40 | const typeof(y) _y = (y); \ 41 | (void) (&_x == &_y); \ 42 | _x > _y ? _x : _y; }) 43 | 44 | #define min_t(type,x,y) \ 45 | ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) 46 | #define max_t(type,x,y) \ 47 | ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) 48 | 49 | void *memset(void *s, int c, size_t n); 50 | void *memcpy(void *dest, const void *src, size_t n); 51 | 52 | int vsprintf(char *str, const char *format, va_list ap) 53 | __attribute__ ((format (printf, 2, 0))); 54 | 55 | int sprintf(char *str, const char *format, ...) 56 | __attribute__ ((format (printf, 2, 0))); 57 | 58 | #define do_div(x, y) ({ \ 59 | uint32_t _x = (x), _y = (y), _q, _r; \ 60 | asm volatile ( \ 61 | "swap %3; " \ 62 | "move.w %3,%0; " \ 63 | "divu.w %4,%0; " /* hi / div */ \ 64 | "move.w %0,%1; " /* stash quotient-hi */ \ 65 | "swap %3; " \ 66 | "move.w %3,%0; " /* lo / div */ \ 67 | "divu.w %4,%0; " \ 68 | "swap %1; " \ 69 | "move.w %0,%1; " /* stash quotient-lo */ \ 70 | "eor.w %0,%0; " \ 71 | "swap %0; " \ 72 | : "=&d" (_r), "=&d" (_q) : "0" (0), "d" (_x), "d" (_y)); \ 73 | (x) = _q; \ 74 | _r; \ 75 | }) 76 | 77 | /* Text/data/BSS address ranges. */ 78 | extern char _stext[], _etext[]; 79 | extern char _sdat[], _edat[], _ldat[]; 80 | extern char _sbss[], _ebss[]; 81 | 82 | /* 83 | * Local variables: 84 | * mode: C 85 | * c-file-style: "Linux" 86 | * c-basic-offset: 4 87 | * tab-width: 4 88 | * indent-tabs-mode: nil 89 | * End: 90 | */ 91 | -------------------------------------------------------------------------------- /base/entry.S: -------------------------------------------------------------------------------- 1 | /* 2 | * dos_entry.S 3 | * 4 | * Entry code for startup from Amiga Workbench or CLI. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | /* Exec Library Vector Offsets */ 13 | #define EXEC_Forbid -0x84 14 | #define EXEC_FindTask -0x126 15 | #define EXEC_GetMsg -0x174 16 | #define EXEC_ReplyMsg -0x17a 17 | #define EXEC_WaitPort -0x180 18 | #define EXEC_OpenLibrary -0x198 19 | #define EXEC_CloseLibrary -0x19e 20 | 21 | /* Graphics Linrary Vector Offsets */ 22 | #define GFX_LoadView -0xde 23 | #define GFX_WaitTOF -0x10e 24 | 25 | /* Offsets into DOS Process structure (extends Exec Task) */ 26 | #define pr_MsgPort 0x5c 27 | #define pr_CLI 0xac 28 | 29 | /* Offsets into GfxBase */ 30 | #define gfx_ActiView 0x22 31 | #define gfx_cop1 0x26 32 | #define gfx_cop2 0x32 33 | 34 | .section .text.init 35 | .global start 36 | start: 37 | move.l 4,a6 38 | 39 | /* Check if we were trackloaded (try to open DOS library). */ 40 | lea .dos(pc),a1 41 | moveq #0,d0 42 | move.l d0,-(sp) /* no wb startup msg yet */ 43 | jsr EXEC_OpenLibrary(a6) 44 | tst.l d0 45 | jeq .nowb /* No DOSBase? We were trackloaded. */ 46 | movel d0,a1 47 | jsr EXEC_CloseLibrary(a6) 48 | 49 | /* Find our Process structure and determine how we were started. */ 50 | sub.l a1,a1 51 | jsr EXEC_FindTask(a6) /* FindTask(NULL) */ 52 | move.l d0,a4 53 | tst.l pr_CLI(a4) /* Running from CLI? */ 54 | bne .nowb 55 | 56 | /* Started from Workbench: wait for start message */ 57 | lea pr_MsgPort(a4),a0 58 | jsr EXEC_WaitPort(a6) 59 | lea pr_MsgPort(a4),a0 60 | jsr EXEC_GetMsg(a6) 61 | move.l d0,(sp) /* Save the startup msg */ 62 | .nowb: 63 | /* graphics.library set up a compatible view */ 64 | lea .gfx(pc),a1 65 | moveq #0,d0 66 | jsr EXEC_OpenLibrary(a6) 67 | move.l d0,a6 68 | move.l gfx_ActiView(a6),-(sp) 69 | sub.l a1,a1 70 | jsr GFX_LoadView(a6) /* LoadView(NULL) */ 71 | jsr GFX_WaitTOF(a6) 72 | jsr GFX_WaitTOF(a6) 73 | move.l a6,-(sp) 74 | 75 | jbsr .begin 76 | move.l d0,d7 77 | 78 | /* d7 = return code */ 79 | /* 0(sp) = gfxbase */ 80 | /* 4(sp) = original view */ 81 | /* 8(sp) = wb msg (or null) */ 82 | 83 | /* Restore original view */ 84 | move.l (sp)+,a6 85 | jsr GFX_WaitTOF(a6) 86 | jsr GFX_WaitTOF(a6) 87 | lea.l (0xdff000).l,a5 88 | move.l gfx_cop1(a6),0x80(a5) /* cop1lc */ 89 | move.l gfx_cop2(a6),0x84(a5) /* cop2lc */ 90 | move.l (sp)+,a1 91 | jsr GFX_LoadView(a6) /* original view */ 92 | 93 | /* Close graphics library */ 94 | movel a6,a1 95 | move.l 4,a6 96 | jsr EXEC_CloseLibrary(a6) 97 | 98 | move.l (sp)+,d3 /* d3 = workbench msg */ 99 | beq .quit 100 | /* Workbench: Return the startup message to our parent */ 101 | jsr EXEC_Forbid(a6) 102 | move.l d3,a1 103 | jsr EXEC_ReplyMsg(a6) 104 | .quit: move.l d7,d0 105 | rts 106 | 107 | .dos: .asciz "dos.library" 108 | .gfx: .asciz "graphics.library" 109 | .balign 2 110 | 111 | .begin: 112 | #include "init.S" 113 | -------------------------------------------------------------------------------- /testkit/RELEASE_NOTES: -------------------------------------------------------------------------------- 1 | ************************************ 2 | ** Amiga Test Kit Release Notes 3 | ** Keir Fraser 4 | ************************************ 5 | 6 | ** v1.21 - 11 November 2023 7 | - Video test cards for CRT maintenance 8 | 9 | ** v1.20 - 18 July 2022 10 | - ADF image is now AmigaDOS-compatible 11 | - Run ATK from floppy disk via Workbench or CLI 12 | 13 | ** v1.19 - 1 July 2022 14 | - floppy: Enhanced calibration and signal tests 15 | - aca500plus: Fix reset sequence 16 | 17 | ** v1.18 - 20 July 2021 18 | - Display ATK version at bottom of every test screen 19 | - Base CIA timer test on true detected VBL frequency 20 | - Fix alternating checkerboard to colour-cycle once per frame 21 | - Remove 30-second motor tiemout from floppy drive signal test 22 | - Do not memory-test in the DC0000-DFFFFF region (issue 39) 23 | 24 | ** v1.17 - 2 July 2021 25 | - Report ROM v47.x as Kickstart 3.2 (issue 46) 26 | - Do not memory-test in the BFxxxx CIA region (issue 39) 27 | - ATK crash report: Split the Exception/PC report line 28 | 29 | ** v1.16 - 26 November 2020 30 | - Report ECS only if both Agnus *and* Denise are ECS 31 | - Video test cards for scaler calibration (hi-res pixel checkerboard) 32 | 33 | ** v1.15 - 4 October 2020 34 | - Floppy: Support HD disks for read/write tests 35 | - Automatically detect HD disk via drive ID 36 | - Floppy: Better READY and Drive ID reporting 37 | - Main Menu improvements: 38 | - Report Kickstart version info 39 | - Convert manu options to two-column format 40 | - Improved analog controller test 41 | - Report min/max pot values 42 | 43 | ** v1.14 - 29 September 2020 44 | - New analog/proportional controller test 45 | - Rename joystick/mouse test to "Controller Ports Test" 46 | 47 | ** v1.13 - 29 September 2020 48 | - Handle and report spurious IRQs 49 | - Report in CIA/Chipset submenu 50 | - Revert to previous behaviour (crash) on spurious IRQ storm 51 | - Crash handler pretty-prints exception name 52 | - Address Error, Line F, ... 53 | 54 | ** v1.12 - 21 August 2020 55 | - New floppy read test: per-track map of read errors 56 | 57 | ** v1.11 - 22 July 2020 58 | - Fix NTSC 8361 "Thin Agnus" detection 59 | - Previously detected as PAL 60 | - Cache/MMU-disable code tweaks 61 | - Fix for GCC 9.3.0 (new release toolchain) 62 | 63 | ** v1.10 - 20 June 2020 64 | - Fix reported startup hang on Apollo 1230 Mk2 accelerator 65 | - Add "All Channels On/Off" to the Audio test menu 66 | 67 | ** v1.9 - 4 June 2020 68 | - Fix startup crash on A600/Furia/68EC020 69 | - "Coprocessor Protocol Violation" guru 70 | - Report 68060 revision id 71 | 72 | ** v1.8 - 4 June 2020 73 | - Audio test includes a Protracker module (Jester/Sanity) 74 | - Uses Frank Wille's Protracker replay routine 75 | - Improved & fixed memory-size reporting in the memory tests 76 | - Binaries are packed using Zopfli for improved loading speed 77 | - Fix some #BERR crashes on Amiga 3000/4000 (Fat Gary) 78 | - Fix Address Fault and Bus Fault crash reports on vanilla 68000 79 | 80 | ** v1.7 - 23 March 2020 81 | - Fix MSM6242 12/24h flag setting in Battery-Backed Clock test 82 | - Simplify and fix the asm startup/init 83 | 84 | ** v1.6 - 7 March 2020 85 | - Extended memory tests 86 | - Custom region test 87 | - Configurable delay between fill & check 88 | - Fix crash on A1200/BlizzardPPC/060 (issue #17) 89 | - Fix hang in RTC tests (issue #18) 90 | 91 | ** v1.5 - 28 September 2019 92 | - Thorough CIA Timer & TOD tests 93 | - Battery-clock test fix for TF534 accelerator (issue #11) 94 | - Floppy drive signal tests allow toggling of STEP and DIR 95 | 96 | ** v1.4 - 3 June 2019 97 | - System Reset option in main menu 98 | 99 | ** v1.3 - 14 March 2019 100 | - Name change: SysTest -> Amiga Test Kit 101 | 102 | ** v1.2 - 30 November 2018 103 | - Implement Set Date & time for Battery Backed Clock (RTC) 104 | -------------------------------------------------------------------------------- /base/mk_adf.py: -------------------------------------------------------------------------------- 1 | # mk_adf.py 2 | # 3 | # Stuff a given bootblock and payload into an output ADF image. 4 | # 5 | # Written & released by Keir Fraser 6 | # 7 | # This is free and unencumbered software released into the public domain. 8 | # See the file COPYING for more details, or visit . 9 | 10 | import struct, sys 11 | 12 | def alloc_in_bitmap(image, start, nr): 13 | # Bootblock is reserved and excluded from bitmap 14 | start -= 2 15 | if start < 0: 16 | nr += start 17 | start = 0 18 | # Bitmap block index is 79th longword in the root block 19 | off = 880*512 + 79*4 20 | bm_block, = struct.unpack(">L", image[off:off+4]) 21 | # Update the bitmap one longword at a time 22 | while nr > 0: 23 | # Create bitmask of blocks we're allocating in this longword 24 | x = ((1 << (start & 31)) - 1) ^ 0xFFFFFFFF 25 | x &= (1 << min(nr + (start & 31), 32)) - 1 26 | # Extract the current value of this longword from the bitmap 27 | off = bm_block * 512 + 4 + (start//32)*4 28 | y = struct.unpack(">L", image[off:off+4])[0] 29 | # Assert that bits we're allocating are currently free 30 | assert x&y == x 31 | # Write back the modified bitmap longword 32 | image[off:off+4] = struct.pack(">L", (x^0xFFFFFFFF)&y) 33 | nr -= 32 - (start & 31) 34 | start += 32 - (start & 31) 35 | # Now recalculate the bitmap block's checksum 36 | off = bm_block * 512 37 | image[off:off+4] = struct.pack(">L", block_checksum(image[off+4:off+512])) 38 | 39 | def block_checksum(block, sum=0): 40 | xs = struct.unpack(">%dL" % (len(block)//4), block) 41 | for x in xs: 42 | sum += x 43 | return -sum & 0xffffffff 44 | 45 | # Amiga bootblock checksum 46 | def bootblock_checksum(bb, sum=0): 47 | xs = struct.unpack(">256L", bb[:1024]) 48 | for x in xs: 49 | sum += x 50 | if sum >= (1<<32): 51 | sum -= (1<<32)-1 52 | return sum 53 | 54 | def main(argv): 55 | with open(argv[1], "rb") as f: 56 | bb_dat = bytearray(f.read()) 57 | with open(argv[2], "rb") as f: 58 | pl_dat = f.read() 59 | with open(argv[3], "rb") as f: 60 | image = bytearray(f.read()) 61 | 62 | bb_len = len(bb_dat) 63 | assert (bb_len & 3) == 0 64 | 65 | _, decompressed_length, _, leeway = struct.unpack(">2I2H", pl_dat[:12]) 66 | pl_dat = pl_dat[12:-2] 67 | pl_len = len(pl_dat) 68 | 69 | # Leeway must account for the padding at end of last block loaded. 70 | leeway += -(bb_len + pl_len) & 511 71 | 72 | # Length of data to load from disk (multiple of 512-byte blocks). 73 | load_len = (bb_len + pl_len + 511) & ~511 74 | 75 | # Amount of memory to allocate in the loader for unpacked payload. 76 | alloc_len = max(load_len, decompressed_length) + leeway 77 | alloc_len += -alloc_len & 3 78 | 79 | print(" BB + Compressed = %u + %u = %u" 80 | % (bb_len, pl_len, bb_len + pl_len)) 81 | print(" Load - Compressed = %u - %u = %u" 82 | % (load_len, pl_len, load_len - pl_len)) 83 | print(" Alloc - Decompressed = %u - %u = %u" 84 | % (alloc_len, decompressed_length, alloc_len - decompressed_length)) 85 | print(" == %u Tracks ==" % ((load_len + 5631) // 5632)) 86 | 87 | # Concatenate everything and splice in the checksum. 88 | bb_dat[14:22] = struct.pack(">2I", alloc_len-load_len, load_len) 89 | dat = bytearray(bb_dat + pl_dat) 90 | dat[4:8] = struct.pack(">L", bootblock_checksum(dat) ^ 0xFFFFFFFF) 91 | 92 | # Splice the concatenated payload into the disk image. 93 | nr_blocks = (len(dat) + 511) // 512 94 | image[:len(dat)] = dat 95 | 96 | # Allocate our payload blocks in the filesystem bitmap. 97 | alloc_in_bitmap(image, 0, nr_blocks) 98 | 99 | # AmigaTestKit writes to the last two tracks in the floppy write test. 100 | # Allocate those tracks in the filesystem bitmap. 101 | alloc_in_bitmap(image, 158*11, 2*11) 102 | 103 | with open(argv[3], "wb") as f: 104 | f.write(image) 105 | 106 | if __name__ == "__main__": 107 | main(sys.argv) 108 | -------------------------------------------------------------------------------- /inflate/depacker_packed.S: -------------------------------------------------------------------------------- 1 | /* 2 | * depacker_packed.S 3 | * 4 | * Packed section of the loader for self-unpacking executables. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | /* LibBase offsets */ 13 | #define LibBase_Version 20 14 | 15 | /* Exec library calls */ 16 | #define Exec_CacheClearU -0x27c 17 | #define Exec_FreeMem -0xd2 18 | 19 | /* On entry: 20 | * a6 = ExecBase; 21 | * (sp) = SegList, d0-d7/a0-a6, return_addresses[2] */ 22 | .text 23 | start: 24 | /* Perform relocations. */ 25 | move.l (sp),a3 26 | lea.l reloc(pc),a2 27 | next_reloc_table: 28 | /* Read next hunk nr (or -1 if last table). */ 29 | move.w (a2)+,d0 30 | jmi relocs_done 31 | jbsr get_seg_base 32 | move.l a0,a1 /* a1 = segment being modified */ 33 | next_reloc_subtable: 34 | /* Read (#relocs, target_hunk). #relocs=0 means last sub-table. */ 35 | move.w (a2)+,d3 /* d3 = #relocs */ 36 | jeq next_reloc_table 37 | move.w (a2)+,d0 38 | jbsr get_seg_base 39 | move.l a0,d1 /* d1 = target segment */ 40 | moveq #-4,d4 /* d4 = reloc offset */ 41 | next_reloc: 42 | /* Relocation offsets are delta-encoded: 43 | * Off(n) = Off(n-1) + 2 * (Delta_n + 1) [1 <= n <= nr] 44 | * Off(0) = -4 45 | * len(Delta_n) = 1 [iff 1 <= Delta_n <= 255] 46 | * = 4 [otherwise] */ 47 | moveq #0,d0 48 | move.b (a2)+,d0 49 | jne 1f 50 | move.b (a2)+,d0 51 | lsl.l #8,d0 52 | move.b (a2)+,d0 53 | lsl.l #8,d0 54 | move.b (a2)+,d0 55 | 1: addq.l #1,d0 56 | add.l d0,d0 57 | add.l d0,d4 /* d4 = new reloc offset */ 58 | add.l d1,(a1,d4.l) /* perform the relocation */ 59 | subq.w #1,d3 60 | jne next_reloc 61 | /* Word-align the relocation-table pointer for the next word access. */ 62 | addq.w #1,a2 63 | move.l a2,d0 64 | and.b #0xfe,d0 65 | move.l d0,a2 66 | jra next_reloc_subtable 67 | 68 | /* a0 = get_seg_base(d0:seg#) */ 69 | get_seg_base: 70 | move.l a3,a0 71 | 1: subq.w #1,d0 72 | jcs 1f 73 | move.l (a0),a0 74 | add.l a0,a0 75 | add.l a0,a0 76 | jra 1b 77 | 1: addq.l #4,a0 78 | rts 79 | 80 | relocs_done: 81 | /* Modify return address to jump at the unpacked exe. */ 82 | move.l (sp)+,a2 /* a2 = first segment BPTR */ 83 | lea.l 4(a2),a0 /* a0 = unpacked entry point */ 84 | move.l a0,15*4(sp) /* modify return address */ 85 | /* Write register-restore epilogue code into the end of hunk#0. We will 86 | * jump there immediately after freeing this segment. It will restore 87 | * registers and then jump at the unpacked executable. */ 88 | lea.l -4(a2),a0 89 | add.l (a0),a0 /* a0 = end of hunk#0 */ 90 | move.w #0x4e75,-(a0) /* rts */ 91 | move.l #0x4cdf7fff,-(a0) /* movem.l (sp)+,d0-d7/a0-a6 */ 92 | move.l a0,-(sp) /* push address of epilogue onto stack. */ 93 | /* Walk the SegList to the end. 94 | * Result: a0-a2 = ptr to final two segments' BPTR fields. */ 95 | 1: move.l (a2),d0 96 | lsl.l #2,d0 97 | jeq 2f 98 | move.l a2,a0 99 | move.l d0,a2 100 | jra 1b 101 | 2: /* Detach this segment from the process's SegList. */ 102 | clr.l (a0) 103 | /* Flush caches if possible. */ 104 | cmp.w #37,LibBase_Version(a6) /* exec.lib_version >= 37? */ 105 | jcs 1f 106 | jsr Exec_CacheClearU(a6) 107 | 1: /* Atomically: Free this segment and jump to epilogue code in hunk0. */ 108 | move.l a2,a1 109 | move.l -(a1),d0 /* a1 = this seg, d0 = this seg length */ 110 | jmp Exec_FreeMem(a6) 111 | 112 | .balign 4 113 | reloc: 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amiga Stuff: Code & Tools for Amigas 2 | 3 | ## Amiga Test Kit 4 | 5 | ![CI Badge][ci-badge] 6 | ![Downloads Badge][downloads-badge] 7 | ![Version Badge][version-badge] 8 | 9 | ### Download the latest release of Amiga Test Kit [here (Github)](https://github.com/keirf/amiga-stuff/releases/download/testkit-v1.21/AmigaTestKit-1.21.zip). 10 | 11 | ### Build From Source (Docker) 12 | 13 | A Docker image has kindly been [supplied (Docker 14 | Hub)](https://hub.docker.com/r/rjnorthrow/atk). You can run it as 15 | follows to generate the latest Amiga Test Kit zip file in your current 16 | directory: 17 | ``` 18 | docker run -v $(pwd):/output --rm -ti rjnorthrow/atk:latest 19 | ``` 20 | 21 | ### Build From Source (Manual Method) 22 | 23 | This is as simple as `make all` when all prerequisites are 24 | installed. The ADF and distribution ZIP file will then be in the 25 | testkit/ folder. 26 | 27 | ### Build Prerequisites 28 | 29 | Pick a location to install your locally-built toolchains, and make sure it is 30 | on your PATH. For example: 31 | ``` 32 | mkdir -p $HOME/install/bin 33 | export PATH=$PATH:$HOME/install/bin 34 | ``` 35 | 36 | #### 1. m68k-elf toolchain 37 | 38 | I recommend binutils-2.34 and gcc-9.3.0, or newer, built with the following 39 | configuration lines on a Linux host or VM. Note these are not 40 | exhaustive toolchain build instructions, as GCC itself has a large number 41 | of prerequisites. You can use the `.github/workflow` scripts for further 42 | hints. 43 | ``` 44 | ../binutils-2.34/configure --prefix=/path/to/install --target=m68k-elf 45 | ../gcc-9.3.0/configure --prefix=/path/to/install --target=m68k-elf --enable-languages=c --disable-libssp 46 | ``` 47 | 48 | On macOS you can instead straightforwardly install from Homebrew: 49 | ``` 50 | brew install m68k-elf-gcc 51 | ``` 52 | 53 | #### 2. m68k-amigaos toolchain 54 | 55 | Clone, build and install bebbo's [amiga-gcc toolchain 56 | (GitHub)][bebbo]. Please follow the README instructions very 57 | carefully. This is especially important if building on macOS, where 58 | careful use of Homebrew-installed tools (including bison!) is required 59 | to avoid cryptic build failures. 60 | 61 | #### 3. Zopfli 62 | 63 | Google's Zopfli is a gzip replacement. It can be installed using your OS package manager, for example `apt` (Ubuntu) or `brew` (macOS). 64 | 65 | #### 4. amitools/xdftool 66 | 67 | This is a Python package which can be installed using pip or pipx. For example: 68 | ``` 69 | pipx install amitools 70 | ``` 71 | 72 | ## Summary 73 | 74 | This is a selection of code that I will add to over time. There are 75 | three main file types, distinguished by suffix: 76 | - **.S** CPP + GAS assembler syntax (for cross-dev environments) 77 | - **.asm** Amiga native asm syntax (Devpac, AsmOne, PhxAss, vasm, Barfly, ...) 78 | - **.c** Somewhat-portable C (I will gladly take patches to make the C code 79 | work outside a GCC/POSIX environment). 80 | 81 | All code is public domain (see the COPYING file). 82 | 83 | 84 | ## File Descriptions 85 | 86 | For detailed build and usage instructions, see 87 | file header comments and run-time help info. 88 | 89 | - **base/** 90 | GNU build rules, initialisation code, utility code and headers. 91 | 92 | - **testkit/** 93 | Amiga Test Kit, built as a Workbench/CLI executable and as a 94 | bootable disk image. 95 | 96 | - **host_tools/kickconv** 97 | Convert Kickstart ROM images: byte-swap, word-split, decrypt, fix checksums. 98 | Especially useful for creating images for burning to EPROM. 99 | 100 | - **attic/crc16_ccitt.S** 101 | Table-driven CRC16-CCITT implementation. 102 | 103 | - **inflate/degzip_{gnu,portable}.c** 104 | Analyse gzip files, extract and write out their raw Deflate streams 105 | (can then be processed by inflate, see below). 106 | Original version for GNU/Linux, and portable version fixed by phx / EAB. 107 | 108 | - **inflate/inflate.{S,asm}** 109 | Small and efficient implementation of Inflate, as specified 110 | in RFC 1951 "DEFLATE Compressed Data Format Specification". 111 | 112 | [ci-badge]: https://github.com/keirf/amiga-stuff/workflows/CI/badge.svg 113 | [downloads-badge]: https://img.shields.io/github/downloads/keirf/amiga-stuff/total 114 | [version-badge]: https://img.shields.io/github/v/release/keirf/amiga-stuff 115 | [bebbo]: https://github.com/bebbo/amiga-gcc 116 | -------------------------------------------------------------------------------- /base/bootblock.S: -------------------------------------------------------------------------------- 1 | /* 2 | * bootblock.S 3 | * 4 | * Amiga floppy-disk bootblock loader. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | /* LibBase offsets */ 13 | #define LibBase_Version 20 14 | 15 | /* Exec library calls */ 16 | #define Exec_AllocMem -0x0c6 17 | #define Exec_FreeMem -0x0d2 18 | #define Exec_DoIO -0x1c8 19 | #define Exec_CacheClearU -0x27c 20 | 21 | /* IORequest.io_Command values */ 22 | #define CMD_READ 2 23 | #define TD_MOTOR 9 24 | 25 | /* struct IORequest offsets */ 26 | #define io_Command 0x1c 27 | #define io_Error 0x1f 28 | #define io_Length 0x24 29 | #define io_Data 0x28 30 | #define io_Offset 0x2c 31 | 32 | /* AllocMem flags */ 33 | #define MEMF_PUBLIC 1 34 | #define MEMF_CHIP 2 35 | #define MEMF_FAST 4 36 | 37 | .text 38 | start: 39 | /* Bootblock header */ 40 | .asciz "DOS" 41 | dc.l 0, 880 42 | bra.b 1f 43 | pl_load_off: dc.l 0 44 | pl_load_len: dc.l 0 45 | 46 | 1: /* Save trackdisk ioreq for later use */ 47 | move.l a1,-(sp) 48 | 49 | /* Allocate memory for the data we're loading from trackdisk. */ 50 | move.l pl_load_off(pc),d0 51 | add.l pl_load_len(pc),d0 52 | moveq #MEMF_PUBLIC|MEMF_CHIP,d1 53 | cmp.w #37,LibBase_Version(a6) 54 | jcs 1f 55 | moveq #MEMF_PUBLIC,d1 /* exec >= 37: don't need to load into chip */ 56 | 1: jsr Exec_AllocMem(a6) 57 | move.l (sp),a1 58 | move.l d0,-(sp) 59 | jeq error 60 | 61 | /* Load the INFLATE routine and the compressed payload data. */ 62 | moveq #3-1,d2 /* max three attempts */ 63 | 1: move.l (sp),d0 64 | add.l pl_load_off(pc),d0 65 | move.l d0,io_Data(a1) 66 | move.l pl_load_len(pc),io_Length(a1) 67 | clr.l io_Offset(a1) 68 | move.w #CMD_READ,io_Command(a1) 69 | jsr Exec_DoIO(a6) 70 | move.l 4(sp),a1 71 | tst.b io_Error(a1) 72 | dbeq d2,1b 73 | jne error 74 | 75 | jbsr motor_off 76 | 77 | /* Allocate memory for INFLATE. We cannot run it from the payload 78 | * area as it will be overwritten during payload decompression. */ 79 | move.l #pl_data-start,d0 80 | moveq #MEMF_PUBLIC,d1 81 | jsr Exec_AllocMem(a6) 82 | move.l 4(sp),a1 83 | move.l d0,-(sp) 84 | jeq error 85 | 86 | /* Copy INFLATE routine from payload to its own allocated area. */ 87 | move.l (sp),a1 88 | move.l 4(sp),a0 89 | add.l pl_load_off(pc),a0 90 | move.l #pl_data-start,d0 91 | lsr.l #2,d0 92 | subq.l #1,d0 93 | 1: move.l (a0)+,(a1)+ 94 | dbf d0,1b 95 | 96 | /* Call INFLATE. */ 97 | jbsr cache_clear 98 | move.l (sp)+,a0 99 | jsr INFLATE-start(a0) 100 | 101 | /* Jump to the decompressed payload. */ 102 | move.l (sp)+,a0 /* a0 = payload data */ 103 | move.l (sp)+,a1 /* a1 = TDIOReq */ 104 | jmp (a0) 105 | 106 | INFLATE: 107 | move.l 4(sp),a4 /* a4 = dest */ 108 | lea pl_data-start(a4),a5 109 | add.l pl_load_off(pc),a5 /* a5 = src */ 110 | jbsr inflate 111 | 112 | jbsr cache_clear 113 | 114 | /* Deallocate the INFLATE memory area and return to the bootblock. */ 115 | lea start(pc),a1 116 | move.l #pl_data-start,d0 117 | move.l (4).w,a6 118 | jmp Exec_FreeMem(a6) 119 | 120 | cache_clear: 121 | /* Code has been written to memory: Flush caches if possible. */ 122 | cmp.w #37,LibBase_Version(a6) /* exec.lib_version >= 37? */ 123 | jcs 1f 124 | jsr Exec_CacheClearU(a6) 125 | 1: rts 126 | 127 | motor_off: 128 | clr.l io_Length(a1) 129 | move.w #TD_MOTOR,io_Command(a1) 130 | jmp Exec_DoIO(a6) 131 | 132 | error: jbsr motor_off 133 | 1: move.w #0xf00,0xdff180 134 | jra 1b 135 | 136 | #include "../inflate/inflate.S" 137 | 138 | .balign 4 139 | pl_data: 140 | -------------------------------------------------------------------------------- /base/inc/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * util.h 3 | * 4 | * General utility functions and definitions. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #if __GNUC__ < 3 13 | #define attribute_used __attribute__((unused)) 14 | #define likely(x) x 15 | #define unlikely(x) x 16 | #else 17 | #define attribute_used __attribute__((used)) 18 | #define likely(x) __builtin_expect((x),1) 19 | #define unlikely(x) __builtin_expect((x),0) 20 | #endif 21 | 22 | #define barrier() asm volatile("" ::: "memory") 23 | 24 | /* Suppresses unwanted array-bounds compiler warnings. */ 25 | #define arrayptr_launder(x) ({ typeof(x) _x; asm("":"=r"(_x):"0"(x)); _x; }) 26 | 27 | #ifndef offsetof 28 | #define offsetof(a,b) __builtin_offsetof(a,b) 29 | #endif 30 | #define container_of(ptr, type, member) ({ \ 31 | typeof( ((type *)0)->member ) *__mptr = (ptr); \ 32 | (type *)( (char *)__mptr - offsetof(type,member) );}) 33 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 34 | 35 | #define min(x,y) ({ \ 36 | const typeof(x) _x = (x); \ 37 | const typeof(y) _y = (y); \ 38 | (void) (&_x == &_y); \ 39 | _x < _y ? _x : _y; }) 40 | 41 | #define max(x,y) ({ \ 42 | const typeof(x) _x = (x); \ 43 | const typeof(y) _y = (y); \ 44 | (void) (&_x == &_y); \ 45 | _x > _y ? _x : _y; }) 46 | 47 | #define min_t(type,x,y) \ 48 | ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) 49 | #define max_t(type,x,y) \ 50 | ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) 51 | 52 | void *memset(void *s, int c, size_t n); 53 | void *memcpy(void *dest, const void *src, size_t n); 54 | void *memmove(void *dest, const void *src, size_t n); 55 | 56 | char *strcpy(char *dest, const char *src); 57 | char *strcat(char *dest, const char *src); 58 | size_t strlen(const char *s); 59 | 60 | void sort(void *base, size_t nmemb, size_t size, 61 | int (*compar)(const void *, const void *)); 62 | 63 | int vsprintf(char *str, const char *format, va_list ap) 64 | __attribute__ ((format (printf, 2, 0))); 65 | 66 | int sprintf(char *str, const char *format, ...) 67 | __attribute__ ((format (printf, 2, 0))); 68 | 69 | /* Division 32:16 -> 32q:16r */ 70 | #define do_div(x, y) ({ \ 71 | uint32_t _x = (x), _y = (y), _q, _r; \ 72 | asm volatile ( \ 73 | "swap %3; " \ 74 | "move.w %3,%0; " \ 75 | "divu.w %4,%0; " /* hi / div */ \ 76 | "move.w %0,%1; " /* stash quotient-hi */ \ 77 | "swap %3; " \ 78 | "move.w %3,%0; " /* lo / div */ \ 79 | "divu.w %4,%0; " \ 80 | "swap %1; " \ 81 | "move.w %0,%1; " /* stash quotient-lo */ \ 82 | "eor.w %0,%0; " \ 83 | "swap %0; " \ 84 | : "=&d" (_r), "=&d" (_q) : "0" (0), "d" (_x), "d" (_y)); \ 85 | (x) = _q; \ 86 | _r; \ 87 | }) 88 | /* Division 32:16 -> 32q */ 89 | uint32_t div32(uint32_t dividend, uint16_t divisor); 90 | 91 | /* Multiply 16:16 -> 32 */ 92 | #define mul32(x, y) ({ \ 93 | uint16_t _x = (x), _y = (y); \ 94 | uint32_t _r; \ 95 | asm volatile ( \ 96 | "mulu.w %1,%0" \ 97 | : "=&d" (_r) : "d" (_y), "0" (_x)); \ 98 | _r; \ 99 | }) 100 | 101 | /* Text/data/BSS address ranges. */ 102 | extern char _start[], _end[]; 103 | extern char _stext[], _etext[]; 104 | extern char _sdat[], _edat[], _ldat[]; 105 | extern char _sbss[], _ebss[]; 106 | 107 | extern char HEAP_END[]; 108 | 109 | /* 110 | * Local variables: 111 | * mode: C 112 | * c-file-style: "Linux" 113 | * c-basic-offset: 4 114 | * tab-width: 4 115 | * indent-tabs-mode: nil 116 | * End: 117 | */ 118 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/inc/amiga_hw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * amiga_hw.h 3 | * 4 | * Register definitions. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | typedef union { 13 | void *p; 14 | uint32_t x; 15 | struct { 16 | uint16_t h, l; 17 | }; 18 | } cust_ptr_t; 19 | 20 | struct amiga_custom { 21 | uint16_t bltddat; 22 | uint16_t dmaconr; 23 | uint16_t vposr; 24 | uint16_t vhposr; 25 | uint16_t dskdatr; 26 | uint16_t joy0dat; 27 | uint16_t joy1dat; 28 | uint16_t clxdat; 29 | uint16_t adkconr; 30 | uint16_t pot0dat; 31 | uint16_t pot1dat; 32 | uint16_t potinp; 33 | uint16_t serdatr; 34 | uint16_t dskbytr; 35 | uint16_t intenar; 36 | uint16_t intreqr; 37 | cust_ptr_t dskpt; 38 | uint16_t dsklen; 39 | uint16_t dskdat; 40 | uint16_t refptr; 41 | uint16_t vposw; 42 | uint16_t vhposw; 43 | uint16_t copcon; 44 | uint16_t serdat; 45 | uint16_t serper; 46 | uint16_t potgo; 47 | uint16_t joytest; 48 | uint16_t strequ; 49 | uint16_t strvbl; 50 | uint16_t strhor; 51 | uint16_t strlong; 52 | uint16_t bltcon0; 53 | uint16_t bltcon1; 54 | uint16_t bltafwm; 55 | uint16_t bltalwm; 56 | cust_ptr_t bltcpt; 57 | cust_ptr_t bltbpt; 58 | cust_ptr_t bltapt; 59 | cust_ptr_t bltdpt; 60 | uint16_t bltsize; 61 | uint16_t _0[3]; 62 | uint16_t bltcmod; 63 | uint16_t bltbmod; 64 | uint16_t bltamod; 65 | uint16_t bltdmod; 66 | uint16_t _1[4]; 67 | uint16_t bltcdat; 68 | uint16_t bltbdat; 69 | uint16_t bltadat; 70 | uint16_t _2[4]; 71 | uint16_t dsksync; 72 | cust_ptr_t cop1lc; 73 | cust_ptr_t cop2lc; 74 | uint16_t copjmp1; 75 | uint16_t copjmp2; 76 | uint16_t copins; 77 | uint16_t diwstrt; 78 | uint16_t diwstop; 79 | uint16_t ddfstrt; 80 | uint16_t ddfstop; 81 | uint16_t dmacon; 82 | uint16_t clxcon; 83 | uint16_t intena; 84 | uint16_t intreq; 85 | uint16_t adkcon; 86 | struct { 87 | cust_ptr_t lc; 88 | uint16_t len; 89 | uint16_t per; 90 | uint16_t vol; 91 | uint16_t dat; 92 | uint16_t _0[2]; 93 | } aud[4]; 94 | cust_ptr_t bpl1pt; 95 | cust_ptr_t bpl2pt; 96 | cust_ptr_t bpl3pt; 97 | cust_ptr_t bpl4pt; 98 | cust_ptr_t bpl5pt; 99 | cust_ptr_t bpl6pt; 100 | cust_ptr_t bpl7pt; 101 | cust_ptr_t bpl8pt; 102 | uint16_t bplcon[4]; 103 | uint16_t bpl1mod; 104 | uint16_t bpl2mod; 105 | uint16_t bplcon4; 106 | uint16_t clxcon2; 107 | uint16_t bpl1dat; 108 | uint16_t bpl2dat; 109 | uint16_t bpl3dat; 110 | uint16_t bpl4dat; 111 | uint16_t bpl5dat; 112 | uint16_t bpl6dat; 113 | uint16_t bpl7dat; 114 | uint16_t bpl8dat; 115 | cust_ptr_t sprpt[8]; 116 | struct { 117 | uint16_t pos; 118 | uint16_t ctl; 119 | uint16_t data; 120 | uint16_t datb; 121 | } spr[8]; 122 | uint16_t color[32]; 123 | uint16_t htotal; 124 | uint16_t hsstop; 125 | uint16_t hbstrt; 126 | uint16_t hbstop; 127 | uint16_t vtotal; 128 | uint16_t vsstop; 129 | uint16_t vbstrt; 130 | uint16_t vbstop; 131 | uint16_t sprhstrt; 132 | uint16_t sprhstop; 133 | uint16_t bplhstrt; 134 | uint16_t bplhstop; 135 | uint16_t hhposw; 136 | uint16_t hhposr; 137 | uint16_t beamcon0; 138 | uint16_t hsstrt; 139 | uint16_t vsstrt; 140 | uint16_t hcenter; 141 | uint16_t diwhigh; 142 | }; 143 | 144 | struct amiga_cia { 145 | uint8_t pra; 146 | uint8_t _0[0xff]; 147 | uint8_t prb; 148 | uint8_t _1[0xff]; 149 | uint8_t ddra; 150 | uint8_t _2[0xff]; 151 | uint8_t ddrb; 152 | uint8_t _3[0xff]; 153 | uint8_t talo; 154 | uint8_t _4[0xff]; 155 | uint8_t tahi; 156 | uint8_t _5[0xff]; 157 | uint8_t tblo; 158 | uint8_t _6[0xff]; 159 | uint8_t tbhi; 160 | uint8_t _7[0xff]; 161 | uint8_t todlow; 162 | uint8_t _8[0xff]; 163 | uint8_t todmid; 164 | uint8_t _9[0xff]; 165 | uint8_t todhi; 166 | uint8_t _a[0xff]; 167 | uint8_t b00; 168 | uint8_t _b[0xff]; 169 | uint8_t sdr; 170 | uint8_t _c[0xff]; 171 | uint8_t icr; 172 | uint8_t _d[0xff]; 173 | uint8_t cra; 174 | uint8_t _e[0xff]; 175 | uint8_t crb; 176 | uint8_t _f[0xff]; 177 | }; 178 | 179 | /* 180 | * Local variables: 181 | * mode: C 182 | * c-file-style: "Linux" 183 | * c-basic-offset: 4 184 | * tab-width: 4 185 | * indent-tabs-mode: nil 186 | * End: 187 | */ 188 | -------------------------------------------------------------------------------- /inflate/test_inflate.py: -------------------------------------------------------------------------------- 1 | # test_inflate.py 2 | # 3 | # Test harness for inflate.S 4 | # 5 | # Written & released by Keir Fraser 6 | # 7 | # This is free and unencumbered software released into the public domain. 8 | # See the file COPYING for more details, or visit . 9 | 10 | import crcmod.predefined 11 | import struct, sys, os 12 | 13 | # Command for creating gzip files. 14 | GZIP = "zopfli --i32 -c" 15 | #GZIP = "gzip -c9" 16 | GUNZIP = "gunzip -c" 17 | 18 | HUNK_HEADER = 0x3f3 19 | HUNK_CODE = 0x3e9 20 | HUNK_END = 0x3f2 21 | PREFIX = '_test_' 22 | 23 | def usage(argv): 24 | print("%s input-files..." % argv[0]) 25 | sys.exit(1) 26 | 27 | def main(argv): 28 | nr = 0 29 | for a in argv[1:]: 30 | if os.path.isfile(a): 31 | test(a) 32 | nr += 1 33 | print("** Tested %u OK" % nr) 34 | 35 | def test(name): 36 | print("Testing '%s'..." % name) 37 | 38 | if name.endswith('.gz'): 39 | # _test_1: Local copy of original gzipped file 40 | os.system('cp "' + name + '" ' + PREFIX + '1') 41 | # _test_0: Uncompressed file 42 | os.system(GUNZIP + ' ' + PREFIX + '1 >' + PREFIX + '0') 43 | else: 44 | # _test_0: Local copy of original uncompressed file 45 | os.system('cp "' + name + '" ' + PREFIX + '0') 46 | # _test_1: Gzipped file 47 | os.system(GZIP + ' ' + PREFIX + '0 >' + PREFIX + '1') 48 | 49 | # CRC of uncompressed data 50 | crc16 = crcmod.predefined.Crc('crc-ccitt-false') 51 | with open(PREFIX + '0', 'rb') as f: 52 | crc16.update(f.read()) 53 | 54 | # _test_2: DEFLATE stream + custom header/footer 55 | os.system('degzip -H ' + PREFIX + '1 ' + PREFIX + '2') 56 | 57 | # _test_3: Register & memory state for 68000 emulator 58 | f = open(PREFIX + '3', 'wb') 59 | # Poison exception vectors and low memory to 0x1000 60 | mem = bytearray([0xde,0xad,0xbe,0xef]) * 0x400 61 | # Marshal the depacker and test harness (Amiga load file) 62 | with open('test_inflate', 'rb') as infile: 63 | (id, x, nr, first, last) = struct.unpack('>5I', infile.read(5*4)) 64 | assert id == HUNK_HEADER and x == 0 65 | assert nr == 1 and first == 0 and last == 0 66 | (x, id, nr) = struct.unpack('>3I', infile.read(3*4)) 67 | assert id == HUNK_CODE and nr == x 68 | mem += infile.read(nr * 4) 69 | (id,) = struct.unpack('>I', infile.read(4)) 70 | assert id == HUNK_END 71 | # Marshal the compressed binary with header (padded to longword) 72 | with open(PREFIX + '2', 'rb') as infile: 73 | mem += infile.read() 74 | mem += bytearray([0]) * (-len(mem)&3) 75 | # Poison remaining longwords to top of memory 76 | remain = (0x200000 - len(mem)) // 4 77 | mem += bytearray([0xde,0xad,0xbe,0xef]) * (remain-1) 78 | # Final return address is magic longword (we check PC after emulation) 79 | mem += bytearray([0xf0,0xe0,0xd0,0xc0]) 80 | f.write(mem) 81 | # Initial register state: only SR,PC,SP really matter 82 | f.write(struct.pack('>18IH6x', 0,0,0,0,0,0,0,0, # D0-D7 83 | 0,0,0,0,0,0,0,0x1ffffc, # A0-A7 84 | 0x1000, # PC 85 | 0, # SSP 86 | 0)) # SR 87 | f.close() 88 | 89 | # Requires m68k_emulate from Github:keirf/Disk-Utilities.git/m68k on PATH 90 | os.system('m68k_emulate ' + PREFIX + '3 ' + PREFIX + '4') 91 | with open(PREFIX + '4', 'rb') as f: 92 | mem = bytes(f.read(0x200000)) 93 | (d0,d1,d2,d3,d4,d5,d6,d7) = struct.unpack('>8I', f.read(8*4)) 94 | (a0,a1,a2,a3,a4,a5,a6,a7) = struct.unpack('>8I', f.read(8*4)) 95 | (pc,ssp,sr) = struct.unpack('>2IH6x', f.read(4*4)) 96 | print('d0: %08x d1: %08x d2: %08x d3: %08x ' 97 | 'd4: %08x d5: %08x d6: %08x d7: %08x' 98 | % (d0,d1,d2,d3,d4,d5,d6,d7)) 99 | print('a0: %08x a1: %08x a2: %08x a3: %08x ' 100 | 'a4: %08x a5: %08x a6: %08x a7: %08x' 101 | % (a0,a1,a2,a3,a4,a5,a6,a7)) 102 | print('pc: %08x ssp: %08x sr: %04x' % (pc,ssp,sr)) 103 | assert pc == 0xf0e0d0c0 104 | assert a7 == 0x200000 105 | assert d0&0xffff == crc16.crcValue # Emulated CRC == our CRC? 106 | assert d0&0xffff == d2&0xffff # Emulated CRC == header CRC? 107 | assert sr&4 # CC_Z (ie crcs match) 108 | # Check CRC in situ in the returned memory buffer 109 | crc16.crcValue = 0xffff 110 | crc16.update(mem[a0:a0+d1]) 111 | assert d0&0xffff == crc16.crcValue # Emulated CRC == our check? 112 | 113 | # All done: clean up 114 | print("") 115 | os.system('rm ' + PREFIX + '*') 116 | 117 | if __name__ == "__main__": 118 | main(sys.argv) 119 | -------------------------------------------------------------------------------- /testkit/mfm.S: -------------------------------------------------------------------------------- 1 | 2 | .section .text 3 | 4 | .global mfm_decode_track, mfm_encode_track 5 | 6 | /* nr_secs = mfm_decode_track(mfmbuf, headers, data, mfm_bytes) */ 7 | mfm_decode_track: 8 | movem.l d0-d7/a0-a3,-(sp) 9 | lea 13*4(sp),a3 /* args: */ 10 | move.l (a3)+,a0 /* mfmbuf */ 11 | move.l (a3)+,a1 /* headers */ 12 | move.l (a3)+,a2 /* data */ 13 | move.l (a3)+,d0 /* mfm_bytes */ 14 | moveq #0,d3 /* nr_sectors */ 15 | move.l #0x55555555,d5 16 | sub.w #1080,d0 17 | lea (a0,d0.w),a3 /* a3 = mfm end - 1 sector */ 18 | .next_sector: 19 | cmpi.w #0x4489,(a0) /* skip 4489 sync */ 20 | jeq .find_sector 21 | movem.l (a0),d0-d1 22 | jbsr decode_mfm_long 23 | move.l d0,(a1)+ /* save the header longword */ 24 | lea 0x30(a0),a0 25 | move.l (a0)+,d4 26 | move.l (a0)+,d0 27 | eor.l d0,d4 /* d4.l = data checksum */ 28 | addq #1,d3 29 | moveq #0x7F,d2 30 | .next_data_long: 31 | move.l 0x200(a0),d1 32 | move.l (a0)+,d0 33 | eor.l d0,d4 34 | eor.l d1,d4 35 | jbsr decode_mfm_long 36 | move.l d0,(a2)+ 37 | dbf d2,.next_data_long 38 | and.l d5,d4 39 | move.l d4,(a1)+ /* save the EOR checksum */ 40 | .find_sector: 41 | cmpa.l a0,a3 /* bail if we scan to end of mfm buffer */ 42 | jls .done 43 | cmpi.w #0x4489,(a0)+ 44 | jne .find_sector 45 | jra .next_sector 46 | .done: move.l d3,(sp) 47 | movem.l (sp)+,d0-d7/a0-a3 48 | rts 49 | 50 | /* d0 = decode_mfm_long(d0 = odd, d1 = even, d5 = 0x55555555) */ 51 | decode_mfm_long: 52 | and.l d5,d0 53 | and.l d5,d1 54 | add.l d0,d0 55 | or.l d1,d0 56 | rts 57 | 58 | /* mfm_encode_track(mfmbuf, tracknr, mfm_bytes, nr_secs) */ 59 | mfm_encode_track: 60 | movem.l d0-d7/a0-a1,-(sp) 61 | lea 11*4(sp),a1 /* args: */ 62 | move.l (a1)+,a0 /* mfmbuf */ 63 | move.l (a1)+,d4 /* tracknr */ 64 | move.l (a1)+,d1 /* mfm_bytes */ 65 | move.l (a1)+,d7 /* nr_secs */ 66 | move.l #0x55555555,d5 67 | move.l #0xaaaaaaaa,d6 68 | lea.l (a0,d1.w),a1 /* a1 = end of mfm buffer */ 69 | move.w d7,d1 70 | lsl.w #8,d1 71 | add.w d1,d1 72 | lea.l (a0,d1.w),a0 /* a0 = end of input data */ 73 | subq.w #1,d7 74 | .sect: moveq #0x7f,d2 75 | moveq #0,d3 76 | move.l d3,-(a1) /* sector gap */ 77 | lea.l -0x200(a1),a1 78 | .lop: move.l -(a0),d0 79 | jbsr encode_mfm_long 80 | eor.l d0,d3 81 | eor.l d1,d3 82 | move.l d0,-(a1) /* even data bits */ 83 | move.l d1,0x200(a1) /* odd data bits */ 84 | dbf d2,.lop 85 | and.l d5,d3 86 | move.l d3,d0 87 | jbsr encode_mfm_long 88 | movem.l d0-d1,-(a1) /* data checksum */ 89 | moveq #0,d0 90 | moveq #9,d1 91 | .lop2: move.l d0,-(a1) /* header checksum + sector label */ 92 | dbf d1,.lop2 93 | move.w #0xff00,d0 /* info.format = 0xff */ 94 | move.b d4,d0 /* info.track */ 95 | swap d0 96 | move.b d7,d0 /* info.sector */ 97 | lsl.w #8,d0 98 | move.b #11,d0 99 | sub.b d7,d0 /* info.sectors_to_gap */ 100 | jbsr encode_mfm_long 101 | movem.l d0-d1,-(a1) /* sector info long */ 102 | eor.l d1,d0 103 | jbsr encode_mfm_long 104 | movem.l d0-d1,40(a1) /* header checksum */ 105 | move.l #0x44014401,-(a1) 106 | move.w #271,d2 107 | .clk: move.l (a1),d0 /* get a longword of data bits */ 108 | move.l d0,d1 109 | roxr.l #1,d0 /* d0 = (X . data_bits) >> 1 -> X */ 110 | rol.l #1,d1 /* d1 = data_bits << 1 */ 111 | or.l d0,d1 112 | not.l d1 /* clock[n] = data[n-1] NOR data[n] */ 113 | and.l d6,d1 114 | or.l d1,(a1)+ /* OR the clock bits into the longword */ 115 | dbf d2,.clk 116 | lea.l -1088(a1),a1 117 | move.l #0x44894489,(a1) /* sync marker */ 118 | dbf d7,.sect 119 | move.l #0xaaaaaaaa,d0 120 | .lop3: move.l d0,-(a1) 121 | cmpa.l a0,a1 122 | jhi .lop3 123 | movem.l (sp)+,d0-d7/a0-a1 124 | rts 125 | 126 | encode_mfm_long: 127 | move.l d0,d1 128 | lsr.l #1,d0 129 | and.l d5,d0 130 | and.l d5,d1 131 | rts 132 | -------------------------------------------------------------------------------- /testkit/ptplayer/custom.i: -------------------------------------------------------------------------------- 1 | * 2 | * Custom chips hardware registers 3 | * 4 | * Written by Frank Wille in 2013, 2016. 5 | * 6 | 7 | CUSTOM equ $dff000 8 | 9 | BLTDDAT equ $000 10 | DMACONR equ $002 11 | VPOSR equ $004 12 | VHPOSR equ $006 13 | DSKDATR equ $008 14 | JOY0DAT equ $00a 15 | JOY1DAT equ $00c 16 | CLXDAT equ $00e 17 | ADKCONR equ $010 18 | POT0DAT equ $012 19 | POT1DAT equ $014 20 | POTGOR equ $016 21 | SERDATR equ $018 22 | DSKBYTR equ $01a 23 | INTENAR equ $01c 24 | INTREQR equ $01e 25 | DSKPT equ $020 26 | DSKPTH equ $020 27 | DSKPTL equ $022 28 | DSKLEN equ $024 29 | DSKDAT equ $026 30 | REFPTR equ $028 31 | VPOSW equ $02a 32 | VHPOSW equ $02c 33 | COPCON equ $02e 34 | SERDAT equ $030 35 | SERPER equ $032 36 | POTGO equ $034 37 | JOYTEST equ $036 38 | STREQU equ $038 39 | STRVBL equ $03a 40 | STRHOR equ $03c 41 | STRLONG equ $03e 42 | BLTCON0 equ $040 43 | BLTCON1 equ $042 44 | BLTAFWM equ $044 45 | BLTALWM equ $046 46 | BLTCPT equ $048 47 | BLTCPTH equ $048 48 | BLTCPTL equ $04a 49 | BLTBPT equ $04c 50 | BLTBPTH equ $04c 51 | BLTBPTL equ $04e 52 | BLTAPT equ $050 53 | BLTAPTH equ $050 54 | BLTAPTL equ $052 55 | BLTDPT equ $054 56 | BLTDPTH equ $054 57 | BLTDPTL equ $056 58 | BLTSIZE equ $058 59 | BLTCMOD equ $060 60 | BLTBMOD equ $062 61 | BLTAMOD equ $064 62 | BLTDMOD equ $066 63 | BLTCDAT equ $070 64 | BLTBDAT equ $072 65 | BLTADAT equ $074 66 | DSKSYNC equ $07e 67 | COP1LC equ $080 68 | COP1LCH equ $080 69 | COP1LCL equ $082 70 | COP2LC equ $084 71 | COP2LCH equ $084 72 | COP2LCL equ $086 73 | COPJMP1 equ $088 74 | COPJMP2 equ $08a 75 | COPINS equ $08c 76 | DIWSTRT equ $08e 77 | DIWSTOP equ $090 78 | DDFSTRT equ $092 79 | DDFSTOP equ $094 80 | DMACON equ $096 81 | CLXCON equ $098 82 | INTENA equ $09a 83 | INTREQ equ $09c 84 | ADKCON equ $09e 85 | AUD0LC equ $0a0 86 | AUD0LCH equ $0a0 87 | AUD0LCL equ $0a2 88 | AUD0LEN equ $0a4 89 | AUD0PER equ $0a6 90 | AUD0VOL equ $0a8 91 | AUD0DAT equ $0aa 92 | AUD1LC equ $0b0 93 | AUD1LCH equ $0b0 94 | AUD1LCL equ $0b2 95 | AUD1LEN equ $0b4 96 | AUD1PER equ $0b6 97 | AUD1VOL equ $0b8 98 | AUD1DAT equ $0ba 99 | AUD2LC equ $0c0 100 | AUD2LCH equ $0c0 101 | AUD2LCL equ $0c2 102 | AUD2LEN equ $0c4 103 | AUD2PER equ $0c6 104 | AUD2VOL equ $0c8 105 | AUD2DAT equ $0ca 106 | AUD3LC equ $0d0 107 | AUD3LCH equ $0d0 108 | AUD3LCL equ $0d2 109 | AUD3LEN equ $0d4 110 | AUD3PER equ $0d6 111 | AUD3VOL equ $0d8 112 | AUD3DAT equ $0da 113 | BPL1PT equ $0e0 114 | BPL1PTH equ $0e0 115 | BPL1PTL equ $0e2 116 | BPL2PT equ $0e4 117 | BPL2PTH equ $0e4 118 | BPL2PTL equ $0e6 119 | BPL3PT equ $0e8 120 | BPL3PTH equ $0e8 121 | BPL3PTL equ $0ea 122 | BPL4PT equ $0ec 123 | BPL4PTH equ $0ec 124 | BPL4PTL equ $0ee 125 | BPL5PT equ $0f0 126 | BPL5PTH equ $0f0 127 | BPL5PTL equ $0f2 128 | BPL6PT equ $0f4 129 | BPL6PTH equ $0f4 130 | BPL6PTL equ $0f6 131 | BPLCON0 equ $100 132 | BPLCON1 equ $102 133 | BPLCON2 equ $104 134 | BPLCON3 equ $106 135 | BPL1MOD equ $108 136 | BPL2MOD equ $10a 137 | BPLCON4 equ $10c 138 | BPL1DAT equ $110 139 | BPL2DAT equ $112 140 | BPL3DAT equ $114 141 | BPL4DAT equ $116 142 | BPL5DAT equ $118 143 | BPL6DAT equ $11a 144 | SPR0PT equ $120 145 | SPR0PTH equ $120 146 | SPR0PTL equ $122 147 | SPR1PT equ $124 148 | SPR1PTH equ $124 149 | SPR1PTL equ $126 150 | SPR2PT equ $128 151 | SPR2PTH equ $128 152 | SPR2PTL equ $12a 153 | SPR3PT equ $12c 154 | SPR3PTH equ $12c 155 | SPR3PTL equ $12e 156 | SPR4PT equ $130 157 | SPR4PTH equ $130 158 | SPR4PTL equ $132 159 | SPR5PT equ $134 160 | SPR5PTH equ $134 161 | SPR5PTL equ $136 162 | SPR6PT equ $138 163 | SPR6PTH equ $138 164 | SPR6PTL equ $13a 165 | SPR7PT equ $13c 166 | SPR7PTH equ $13c 167 | SPR7PTL equ $13e 168 | SPR0POS equ $140 169 | SPR0CTL equ $142 170 | SPR0DATA equ $144 171 | SPR0DATB equ $146 172 | SPR1POS equ $148 173 | SPR1CTL equ $14a 174 | SPR1DATA equ $14c 175 | SPR1DATB equ $14e 176 | SPR2POS equ $150 177 | SPR2CTL equ $152 178 | SPR2DATA equ $154 179 | SPR2DATB equ $156 180 | SPR3POS equ $158 181 | SPR3CTL equ $15a 182 | SPR3DATA equ $15c 183 | SPR3DATB equ $15e 184 | SPR4POS equ $160 185 | SPR4CTL equ $162 186 | SPR4DATA equ $164 187 | SPR4DATB equ $166 188 | SPR5POS equ $168 189 | SPR5CTL equ $16a 190 | SPR5DATA equ $16c 191 | SPR5DATB equ $16e 192 | SPR6POS equ $170 193 | SPR6CTL equ $172 194 | SPR6DATA equ $174 195 | SPR6DATB equ $176 196 | SPR7POS equ $178 197 | SPR7CTL equ $17a 198 | SPR7DATA equ $17c 199 | SPR7DATB equ $17e 200 | COLOR00 equ $180 201 | COLOR01 equ $182 202 | COLOR02 equ $184 203 | COLOR03 equ $186 204 | COLOR04 equ $188 205 | COLOR05 equ $18a 206 | COLOR06 equ $18c 207 | COLOR07 equ $18e 208 | COLOR08 equ $190 209 | COLOR09 equ $192 210 | COLOR10 equ $194 211 | COLOR11 equ $196 212 | COLOR12 equ $198 213 | COLOR13 equ $19a 214 | COLOR14 equ $19c 215 | COLOR15 equ $19e 216 | COLOR16 equ $1a0 217 | COLOR17 equ $1a2 218 | COLOR18 equ $1a4 219 | COLOR19 equ $1a6 220 | COLOR20 equ $1a8 221 | COLOR21 equ $1aa 222 | COLOR22 equ $1ac 223 | COLOR23 equ $1ae 224 | COLOR24 equ $1b0 225 | COLOR25 equ $1b2 226 | COLOR26 equ $1b4 227 | COLOR27 equ $1b6 228 | COLOR28 equ $1b8 229 | COLOR29 equ $1ba 230 | COLOR30 equ $1bc 231 | COLOR31 equ $1be 232 | HTOTAL equ $1c0 233 | HSSTOP equ $1c2 234 | HBSTRT equ $1c4 235 | HBSTOP equ $1c6 236 | VTOTAL equ $1c8 237 | VSSTOP equ $1ca 238 | VBSTRT equ $1cc 239 | VBSTOP equ $1ce 240 | SPRHSTRT equ $1d0 241 | SPRHSTOP equ $1d2 242 | BPLHSTRT equ $1d4 243 | BPLHSTOP equ $1d6 244 | HHPOSW equ $1d8 245 | HHPOSR equ $1da 246 | BEAMCON0 equ $1dc 247 | HSSTRT equ $1de 248 | VSSTRT equ $1e0 249 | HCENTER equ $1e2 250 | DIWHIGH equ $1e4 251 | BPLHMOD equ $1e6 252 | SPRHPT equ $1e8 253 | SPRHPTH equ $1e8 254 | SPRHPTL equ $1ea 255 | BPLHPT equ $1ec 256 | BPLHPTH equ $1ec 257 | BPLHPTL equ $1ee 258 | FMODE equ $1fc 259 | -------------------------------------------------------------------------------- /testkit/audio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * audio.c 3 | * 4 | * Test standard Amiga audio hardware. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #include "testkit.h" 13 | #include "ptplayer/wrapper.c" 14 | 15 | extern uint8_t mod[]; 16 | enum { SOUND_mod, SOUND_low, SOUND_high, SOUND_max }; 17 | 18 | static void mod_start(uint8_t channels) 19 | { 20 | mt_install_cia(is_pal); 21 | mt_init(mod, 0); 22 | mt_disablemask(~channels); 23 | _mt_Enable = 1; 24 | } 25 | 26 | static void mod_stop(void) 27 | { 28 | mt_end(); 29 | mt_remove_cia(); 30 | ciab_init(); 31 | } 32 | 33 | static void tone_stop(void) 34 | { 35 | unsigned int i; 36 | for (i = 0; i < 4; i++) 37 | cust->aud[i].vol = 0; 38 | cust->dmacon = DMA_AUDxEN; /* dma off */ 39 | } 40 | 41 | static void tone_toggle(uint8_t sound, uint8_t channels, unsigned int i) 42 | { 43 | if (!(channels & (1u << i))) 44 | cust->aud[i].vol = 0; 45 | else if (sound != SOUND_mod) 46 | cust->aud[i].vol = 64; 47 | print_text_box(29, 2+i, channels & (1u<pra |= CIAAPRA_LED; 65 | 66 | /* Generate the 500Hz waveform. */ 67 | for (i = 0; i < 10; i++) { 68 | aud_500hz[i] = sine[i]; 69 | aud_500hz[10+i] = sine[10-i]; 70 | aud_500hz[20+i] = -sine[i]; 71 | aud_500hz[30+i] = -sine[10-i]; 72 | } 73 | 74 | /* Generate the 10kHz waveform. */ 75 | aud_10khz[0] = 127; 76 | aud_10khz[1] = -127; 77 | 78 | print_menu_nav_line(); 79 | 80 | r.x = 14; 81 | sprintf(s, "-- Audio --"); 82 | print_line(&r); 83 | r.y += 2; 84 | r.x = 8; 85 | 86 | sprintf(s, "$1 Channel 0/L$ - ON"); 87 | print_line(&r); 88 | r.y++; 89 | sprintf(s, "$2 Channel 1/R$ - ON"); 90 | print_line(&r); 91 | r.y++; 92 | sprintf(s, "$3 Channel 2/R$ - ON"); 93 | print_line(&r); 94 | r.y++; 95 | sprintf(s, "$4 Channel 3/L$ - ON"); 96 | print_line(&r); 97 | r.y++; 98 | sprintf(s, "$5 Sound $ - Music"); 99 | print_line(&r); 100 | r.y++; 101 | sprintf(s, "$6 L.P. Filter$ - OFF"); 102 | print_line(&r); 103 | r.y++; 104 | sprintf(s, "$7 All Channels On/Off$"); 105 | print_line(&r); 106 | r.y += 2; 107 | r.x -= 3; 108 | sprintf(s, "Music: \"Spice It Up\" by Jester/Sanity"); 109 | print_line(&r); 110 | r.y++; 111 | sprintf(s, "Protracker Play Routine by Frank Wille"); 112 | print_line(&r); 113 | 114 | /* period = cpu_hz / (2 * nr_samples * frequency) */ 115 | period = div32(div32(div32(cpu_hz, 2), nr_500hz_samples), 500/*Hz*/); 116 | 117 | mod_start(channels); 118 | 119 | for (;;) { 120 | while (!(key = keycode_buffer) && !do_exit) 121 | continue; 122 | keycode_buffer = 0; 123 | 124 | /* ESC also means exit */ 125 | if (do_exit || (key == K_ESC)) 126 | break; 127 | 128 | key -= K_F1; 129 | if (key < 4) { 130 | /* F1-F4: Switch channel 0-3 */ 131 | channels ^= 1u << key; 132 | mt_disablemask(~channels); 133 | tone_toggle(sound, channels, key); 134 | } else if (key == 4) { 135 | /* F5: Sound */ 136 | if (sound == SOUND_mod) 137 | mod_stop(); 138 | tone_stop(); 139 | if (++sound == SOUND_max) 140 | sound = 0; 141 | switch (sound) { 142 | case SOUND_mod: 143 | mod_start(channels); 144 | print_text_box(28, 6, "Music "); 145 | break; 146 | case SOUND_low: 147 | for (i = 0; i < 4; i++) { 148 | cust->aud[i].lc.p = aud_500hz; 149 | cust->aud[i].len = nr_500hz_samples / 2; 150 | cust->aud[i].per = (uint16_t)period; 151 | cust->aud[i].vol = (channels & (1u << i)) ? 64 : 0; 152 | } 153 | cust->dmacon = DMA_SETCLR | DMA_AUDxEN; /* dma on */ 154 | print_text_box(28, 6, "500Hz Sine "); 155 | break; 156 | case SOUND_high: 157 | for (i = 0; i < 4; i++) { 158 | cust->aud[i].lc.p = aud_10khz; 159 | cust->aud[i].len = nr_10khz_samples / 2; 160 | cust->aud[i].per = (uint16_t)period; 161 | cust->aud[i].vol = (channels & (1u << i)) ? 64 : 0; 162 | } 163 | cust->dmacon = DMA_SETCLR | DMA_AUDxEN; /* dma on */ 164 | print_text_box(28, 6, "10kHz Square"); 165 | break; 166 | } 167 | } else if (key == 5) { 168 | /* F6: Low Pass Filter */ 169 | ciaa->pra ^= CIAAPRA_LED; 170 | print_text_box(29, 7, (ciaa->pra & CIAAPRA_LED) ? "FF" : "N "); 171 | } else if (key == 6) { 172 | /* F7: All Channels On/Off */ 173 | channels = channels ? 0 : 0xf; 174 | mt_disablemask(~channels); 175 | for (i = 0; i < 4; i++) 176 | tone_toggle(sound, channels, i); 177 | } 178 | } 179 | 180 | /* Clean up. */ 181 | if (sound == SOUND_mod) 182 | mod_stop(); 183 | tone_stop(); 184 | ciaa->pra &= ~CIAAPRA_LED; 185 | } 186 | 187 | asm ( 188 | " .data \n" 189 | "mod: .incbin \"ptplayer/spice.mod\"\n" 190 | " .text \n" 191 | ); 192 | -------------------------------------------------------------------------------- /overscan/overscan.c: -------------------------------------------------------------------------------- 1 | /* 2 | * overscan.c 3 | * 4 | * Overscan display example for screen setup. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | static volatile struct amiga_custom * const cust = 13 | (struct amiga_custom *)0xdff000; 14 | static volatile struct amiga_cia * const ciaa = 15 | (struct amiga_cia *)0x0bfe001; 16 | 17 | #define IRQ(name) \ 18 | static void c_##name(void) attribute_used; \ 19 | void name(void); \ 20 | asm ( \ 21 | #name": \n" \ 22 | " movem.l %d0-%d1/%a0-%a1,-(%sp) \n" \ 23 | " jbsr c_"#name" \n" \ 24 | " movem.l (%sp)+,%d0-%d1/%a0-%a1 \n" \ 25 | " rte \n" \ 26 | ) 27 | 28 | /* Bog standard PAL 320x256 lo-res display. */ 29 | static uint16_t copper_normal[] = { 30 | 0x008e, 0x2c81, /* diwstrt */ 31 | 0x0090, 0x2cc1, /* diwstop */ 32 | 0x0092, 0x0038, /* ddfstrt */ 33 | 0x0094, 0x00d0, /* ddfstop */ 34 | 0x0100, 0x2200, /* bplcon0 */ 35 | 0x0102, 0x0000, /* bplcon1 */ 36 | 0x0104, 0x0000, /* bplcon2 */ 37 | 0x0108, 0x0000, /* bpl1mod */ 38 | 0x010a, 0x0000, /* bpl2mod */ 39 | 0x00e0, 0x0002, /* bpl1pth */ 40 | 0x00e2, 0x0000, /* bpl1ptl */ 41 | 0x00e4, 0x0002, /* bpl2pth */ 42 | 0x00e6, 0x4000, /* bpl2ptl */ 43 | 0x0182, 0x00f0, /* col01 */ 44 | 0x0184, 0x000f, /* col02 */ 45 | 0x0186, 0x0f0f, /* col03 */ 46 | 0x0180, 0x0f00, /* col00 */ 47 | 0xffff, 0xfffe, 48 | }; 49 | 50 | /* Overscan values taken from Rink a Dink: Redux. 352x272 resolution. 51 | * Left border: 16px overscan 52 | * Right border: 16px overscan 53 | * Top border: 12px overscan 54 | * Bottom border: 4px overscan (ungenerous? but okay on my lcd tv) */ 55 | static uint16_t copper_overscan[] = { 56 | 0x008e, 0x2071, /* diwstrt */ 57 | 0x0090, 0x30d1, /* diwstop */ 58 | 0x0092, 0x0030, /* ddfstrt */ 59 | 0x0094, 0x00d8, /* ddfstop */ 60 | 0x0100, 0x2200, /* bplcon0 */ 61 | 0x0102, 0x0000, /* bplcon1 */ 62 | 0x0104, 0x0000, /* bplcon2 */ 63 | 0x0108, 0x0000, /* bpl1mod */ 64 | 0x010a, 0x0000, /* bpl2mod */ 65 | 0x00e0, 0x0002, /* bpl1pth */ 66 | 0x00e2, 0x8000, /* bpl1ptl */ 67 | 0x00e4, 0x0002, /* bpl2pth */ 68 | 0x00e6, 0xc000, /* bpl2ptl */ 69 | 0x0182, 0x00f0, /* col01 */ 70 | 0x0184, 0x000f, /* col02 */ 71 | 0x0186, 0x0f0f, /* col03 */ 72 | 0x0180, 0x0f00, /* col00 */ 73 | /* Horizontal positions e2->02 inclusive are indistinguishable and all 74 | * occur before the end of 16px overscan. */ 75 | 0x8001, 0xfffe, 76 | 0x0182, 0x0fff, /* Oh no! White appears before end of overscan! */ 77 | 0x8101, 0xfffe, 78 | 0x0182, 0x00f0, 79 | /* Horizontal positions 04+ occur during or immediately before horizontal 80 | * blank. Position 06 certainly hides the colour change behind flyback. */ 81 | 0x9007, 0xfffe, 82 | 0x0180, 0x0fff, /* All good! White does not appear mid-line. */ 83 | 0x9107, 0xfffe, 84 | 0x0180, 0x0f00, 85 | 0xffff, 0xfffe, 86 | }; 87 | 88 | /* As above but more generous 12px overscan on bottom border (352x280 res.) 89 | * Avoids blank (i.e, RED) bottom border on my CRT. I also tried 8px overscan 90 | * but that wasn't quite enough with a relaxed CRT vertical-size setting. */ 91 | static uint16_t copper_overscan_xtra[] = { 92 | 0x008e, 0x2071, /* diwstrt */ 93 | 0x0090, 0x38d1, /* diwstop */ 94 | 0x0092, 0x0030, /* ddfstrt */ 95 | 0x0094, 0x00d8, /* ddfstop */ 96 | 0x0100, 0x2200, /* bplcon0 */ 97 | 0x0102, 0x0000, /* bplcon1 */ 98 | 0x0104, 0x0000, /* bplcon2 */ 99 | 0x0108, 0x0000, /* bpl1mod */ 100 | 0x010a, 0x0000, /* bpl2mod */ 101 | 0x00e0, 0x0002, /* bpl1pth */ 102 | 0x00e2, 0x8000, /* bpl1ptl */ 103 | 0x00e4, 0x0002, /* bpl2pth */ 104 | 0x00e6, 0xc000, /* bpl2ptl */ 105 | 0x0182, 0x00f0, /* col01 */ 106 | 0x0184, 0x000f, /* col02 */ 107 | 0x0186, 0x0f0f, /* col03 */ 108 | 0x0180, 0x0f00, /* col00 */ 109 | 0xffff, 0xfffe, 110 | }; 111 | 112 | /* c.w Pac-Mania: top +43px, bottom -1px(!), left +16px, right +4px 113 | * Bottom border is bizarre. Limited right overscan maybe explained by fact 114 | * default display is often visibly right-shifted on television sets. */ 115 | 116 | static void wait_button(void) 117 | { 118 | while ((ciaa->pra & 0xc0) == 0xc0) 119 | continue; 120 | /* Debounce */ 121 | cust->intreq = 0x20; 122 | while (!(cust->intreqr & 0x20)) 123 | continue; 124 | while ((ciaa->pra & 0xc0) != 0xc0) 125 | continue; 126 | /* Debounce */ 127 | cust->intreq = 0x20; 128 | while (!(cust->intreqr & 0x20)) 129 | continue; 130 | } 131 | 132 | void cstart(void) 133 | { 134 | uint16_t i; 135 | char *p; 136 | 137 | /* Clear BSS. */ 138 | memset(_sbss, 0, _ebss-_sbss); 139 | 140 | /* Normal display: all BLUE; background color RED. */ 141 | p = (char *)0x20000; 142 | memset(p, 0x00, 0x4000); 143 | p = (char *)0x24000; 144 | memset(p, 0xff, 0x4000); 145 | 146 | /* Overscan display: GREEN in overscan border. BLUE in middle. */ 147 | p = (char *)0x28000; 148 | memset(p, 0x00, 0x4000); 149 | for (i = 0; i < 12; i++) { 150 | memset(p, 0xff, 352/8); 151 | p += 352/8; 152 | } 153 | for (i = 0; i < 256; i++) { 154 | memset(p, 0xff, 16/8); 155 | memset(p+336/8, 0xff, 16/8); 156 | p += 352/8; 157 | } 158 | for (i = 0; i < 12; i++) { 159 | memset(p, 0xff, 352/8); 160 | p += 352/8; 161 | } 162 | p = (char *)0x2c000; 163 | memset(p, 0x00, 0x4000); 164 | p += 12*(352/8); 165 | for (i = 0; i < 256; i++) { 166 | memset(p+16/8, 0xff, 320/8); 167 | p += 352/8; 168 | } 169 | 170 | cust->cop1lc.p = copper_normal; 171 | cust->dmacon = 0x81c8; /* enable copper/bitplane DMA */ 172 | 173 | /* Switch display size on LMB/Fire. */ 174 | for (;;) { 175 | wait_button(); 176 | cust->cop1lc.p = copper_overscan; 177 | wait_button(); 178 | cust->cop1lc.p = copper_overscan_xtra; 179 | wait_button(); 180 | cust->cop1lc.p = copper_normal; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /base/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * util.c 3 | * 4 | * General-purpose utility functions. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | static void do_putch(char **p, char *end, char c) 13 | { 14 | if (*p < end) 15 | **p = c; 16 | (*p)++; 17 | } 18 | 19 | int vsnprintf(char *str, size_t size, const char *format, va_list ap) 20 | { 21 | unsigned int x, flags; 22 | int width; 23 | char c, *p = str, *end = p + size - 1, tmp[12], *q; 24 | 25 | while ((c = *format++) != '\0') { 26 | if (c != '%') { 27 | do_putch(&p, end, c); 28 | continue; 29 | } 30 | 31 | flags = width = 0; 32 | #define BASE (31u << 0) 33 | #define UPPER ( 1u << 8) 34 | #define SIGN ( 1u << 9) 35 | #define ALTERNATE ( 1u << 10) 36 | #define ZEROPAD ( 1u << 11) 37 | #define CHAR ( 1u << 12) 38 | #define SHORT ( 1u << 13) 39 | 40 | more: 41 | switch (c = *format++) { 42 | case '#': 43 | flags |= ALTERNATE; 44 | goto more; 45 | case '0': 46 | flags |= ZEROPAD; 47 | goto more; 48 | case '1'...'9': 49 | width = c-'0'; 50 | while (((c = *format) >= '0') && (c <= '9')) { 51 | width = width*10 + c-'0'; 52 | format++; 53 | } 54 | goto more; 55 | case 'h': 56 | if ((c = *format) == 'h') { 57 | flags |= CHAR; 58 | format++; 59 | } else { 60 | flags |= SHORT; 61 | } 62 | goto more; 63 | case 'o': 64 | flags |= 8; 65 | break; 66 | case 'd': 67 | case 'i': 68 | flags |= SIGN; 69 | case 'u': 70 | flags |= 10; 71 | break; 72 | case 'X': 73 | flags |= UPPER; 74 | case 'x': 75 | case 'p': 76 | flags |= 16; 77 | break; 78 | case 's': 79 | q = va_arg(ap, char *); 80 | while ((c = *q++) != '\0') { 81 | do_putch(&p, end, c); 82 | width--; 83 | } 84 | while (width-- > 0) 85 | do_putch(&p, end, ' '); 86 | continue; 87 | case 'c': 88 | c = va_arg(ap, unsigned int); 89 | default: 90 | do_putch(&p, end, c); 91 | continue; 92 | } 93 | 94 | x = va_arg(ap, unsigned int); 95 | 96 | if (flags & CHAR) { 97 | if (flags & SIGN) 98 | x = (char)x; 99 | else 100 | x = (unsigned char)x; 101 | } else if (flags & SHORT) { 102 | if (flags & SIGN) 103 | x = (short)x; 104 | else 105 | x = (unsigned short)x; 106 | } 107 | 108 | if ((flags & SIGN) && ((int)x < 0)) { 109 | if (flags & ZEROPAD) { 110 | do_putch(&p, end, '-'); 111 | flags &= ~SIGN; 112 | } 113 | width--; 114 | x = -x; 115 | } else { 116 | flags &= ~SIGN; 117 | } 118 | 119 | if (flags & ALTERNATE) { 120 | if (((flags & BASE) == 8) || ((flags & BASE) == 16)) { 121 | do_putch(&p, end, '0'); 122 | width--; 123 | } 124 | if ((flags & BASE) == 16) { 125 | do_putch(&p, end, 'x'); 126 | width--; 127 | } 128 | } 129 | 130 | if (x == 0) { 131 | q = tmp; 132 | *q++ = '0'; 133 | } else { 134 | for (q = tmp; x; q++) 135 | *q = ((flags & UPPER) 136 | ? "0123456789ABCDEF" 137 | : "0123456789abcdef") [do_div(x, flags&BASE)]; 138 | } 139 | while (width-- > (q-tmp)) 140 | do_putch(&p, end, (flags & ZEROPAD) ? '0' : ' '); 141 | if (flags & SIGN) 142 | do_putch(&p, end, '-'); 143 | while (q != tmp) 144 | do_putch(&p, end, *--q); 145 | }; 146 | 147 | if (p <= end) 148 | *p = '\0'; 149 | 150 | return p - str; 151 | } 152 | 153 | int sprintf(char *str, const char *format, ...) 154 | { 155 | va_list ap; 156 | int n; 157 | 158 | va_start(ap, format); 159 | n = vsnprintf(str, 256/* XXX */, format, ap); 160 | va_end(ap); 161 | 162 | return n; 163 | } 164 | 165 | void *memset(void *s, int c, size_t n) 166 | { 167 | char *p = s; 168 | while (n--) 169 | *p++ = c; 170 | return s; 171 | } 172 | 173 | void *memcpy(void *dest, const void *src, size_t n) 174 | { 175 | char *p = dest; 176 | const char *q = src; 177 | while (n--) 178 | *p++ = *q++; 179 | return dest; 180 | } 181 | 182 | void *memmove(void *dest, const void *src, size_t n) 183 | { 184 | char *p; 185 | const char *q; 186 | if (dest < src) 187 | return memcpy(dest, src, n); 188 | p = dest; p += n; 189 | q = src; q += n; 190 | while (n--) 191 | *--p = *--q; 192 | return dest; 193 | } 194 | 195 | char *strcpy(char *dest, const char *src) 196 | { 197 | char *p = dest; 198 | while ((*p++ = *src++) != '\0') 199 | continue; 200 | return dest; 201 | } 202 | 203 | char *strcat(char *dest, const char *src) 204 | { 205 | char *p = dest; 206 | while (*p != '\0') 207 | p++; 208 | while ((*p++ = *src++) != '\0') 209 | continue; 210 | return p; 211 | } 212 | 213 | size_t strlen(const char *s) 214 | { 215 | const char *p = s; 216 | while (*p != '\0') 217 | p++; 218 | return p - s; 219 | } 220 | 221 | void sort(void *base, size_t nmemb, size_t size, 222 | int (*compar)(const void *, const void *)) 223 | { 224 | int16_t i; 225 | char _p[32], *p = base, *q; 226 | 227 | for (i = 1; i < nmemb; i++) { 228 | p += size; 229 | for (q = p - size; q >= (char *)base; q -= size) 230 | if (compar(p, q) > 0) 231 | break; 232 | q += size; 233 | if (p != q) { 234 | memcpy(&_p, p, size); 235 | memmove(q + size, q, p - q); 236 | memcpy(q, &_p, size); 237 | } 238 | } 239 | } 240 | 241 | uint32_t div32(uint32_t dividend, uint16_t divisor) 242 | { 243 | do_div(dividend, divisor); 244 | return dividend; 245 | } 246 | 247 | /* 248 | * Local variables: 249 | * mode: C 250 | * c-file-style: "Linux" 251 | * c-basic-offset: 4 252 | * tab-width: 4 253 | * indent-tabs-mode: nil 254 | * End: 255 | */ 256 | -------------------------------------------------------------------------------- /base/inc/amiga_hw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * amiga_hw.h 3 | * 4 | * Register definitions. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | typedef union { 13 | void *p; 14 | uint32_t x; 15 | struct { 16 | uint16_t h, l; 17 | }; 18 | } cust_ptr_t; 19 | 20 | struct amiga_custom { 21 | uint16_t bltddat; 22 | uint16_t dmaconr; 23 | uint16_t vposr; 24 | uint16_t vhposr; 25 | uint16_t dskdatr; 26 | uint16_t joy0dat; 27 | uint16_t joy1dat; 28 | uint16_t clxdat; 29 | uint16_t adkconr; 30 | uint16_t pot0dat; 31 | uint16_t pot1dat; 32 | uint16_t potinp; 33 | uint16_t serdatr; 34 | uint16_t dskbytr; 35 | uint16_t intenar; 36 | uint16_t intreqr; 37 | cust_ptr_t dskpt; 38 | uint16_t dsklen; 39 | uint16_t dskdat; 40 | uint16_t refptr; 41 | uint16_t vposw; 42 | uint16_t vhposw; 43 | uint16_t copcon; 44 | uint16_t serdat; 45 | uint16_t serper; 46 | uint16_t potgo; 47 | uint16_t joytest; 48 | uint16_t strequ; 49 | uint16_t strvbl; 50 | uint16_t strhor; 51 | uint16_t strlong; 52 | uint16_t bltcon0; 53 | uint16_t bltcon1; 54 | uint16_t bltafwm; 55 | uint16_t bltalwm; 56 | cust_ptr_t bltcpt; 57 | cust_ptr_t bltbpt; 58 | cust_ptr_t bltapt; 59 | cust_ptr_t bltdpt; 60 | uint16_t bltsize; 61 | uint16_t _0[3]; 62 | uint16_t bltcmod; 63 | uint16_t bltbmod; 64 | uint16_t bltamod; 65 | uint16_t bltdmod; 66 | uint16_t _1[4]; 67 | uint16_t bltcdat; 68 | uint16_t bltbdat; 69 | uint16_t bltadat; 70 | uint16_t _2[3]; 71 | uint16_t deniseid; 72 | uint16_t dsksync; 73 | cust_ptr_t cop1lc; 74 | cust_ptr_t cop2lc; 75 | uint16_t copjmp1; 76 | uint16_t copjmp2; 77 | uint16_t copins; 78 | uint16_t diwstrt; 79 | uint16_t diwstop; 80 | uint16_t ddfstrt; 81 | uint16_t ddfstop; 82 | uint16_t dmacon; 83 | uint16_t clxcon; 84 | uint16_t intena; 85 | uint16_t intreq; 86 | uint16_t adkcon; 87 | struct { 88 | cust_ptr_t lc; 89 | uint16_t len; 90 | uint16_t per; 91 | uint16_t vol; 92 | uint16_t dat; 93 | uint16_t _0[2]; 94 | } aud[4]; 95 | cust_ptr_t bpl1pt; 96 | cust_ptr_t bpl2pt; 97 | cust_ptr_t bpl3pt; 98 | cust_ptr_t bpl4pt; 99 | cust_ptr_t bpl5pt; 100 | cust_ptr_t bpl6pt; 101 | cust_ptr_t bpl7pt; 102 | cust_ptr_t bpl8pt; 103 | uint16_t bplcon[4]; 104 | uint16_t bpl1mod; 105 | uint16_t bpl2mod; 106 | uint16_t bplcon4; 107 | uint16_t clxcon2; 108 | uint16_t bpl1dat; 109 | uint16_t bpl2dat; 110 | uint16_t bpl3dat; 111 | uint16_t bpl4dat; 112 | uint16_t bpl5dat; 113 | uint16_t bpl6dat; 114 | uint16_t bpl7dat; 115 | uint16_t bpl8dat; 116 | cust_ptr_t sprpt[8]; 117 | struct { 118 | uint16_t pos; 119 | uint16_t ctl; 120 | uint16_t data; 121 | uint16_t datb; 122 | } spr[8]; 123 | uint16_t color[32]; 124 | uint16_t htotal; 125 | uint16_t hsstop; 126 | uint16_t hbstrt; 127 | uint16_t hbstop; 128 | uint16_t vtotal; 129 | uint16_t vsstop; 130 | uint16_t vbstrt; 131 | uint16_t vbstop; 132 | uint16_t sprhstrt; 133 | uint16_t sprhstop; 134 | uint16_t bplhstrt; 135 | uint16_t bplhstop; 136 | uint16_t hhposw; 137 | uint16_t hhposr; 138 | uint16_t beamcon0; 139 | uint16_t hsstrt; 140 | uint16_t vsstrt; 141 | uint16_t hcenter; 142 | uint16_t diwhigh; 143 | }; 144 | 145 | struct amiga_cia { 146 | uint8_t pra; 147 | uint8_t _0[0xff]; 148 | uint8_t prb; 149 | uint8_t _1[0xff]; 150 | uint8_t ddra; 151 | uint8_t _2[0xff]; 152 | uint8_t ddrb; 153 | uint8_t _3[0xff]; 154 | uint8_t talo; 155 | uint8_t _4[0xff]; 156 | uint8_t tahi; 157 | uint8_t _5[0xff]; 158 | uint8_t tblo; 159 | uint8_t _6[0xff]; 160 | uint8_t tbhi; 161 | uint8_t _7[0xff]; 162 | uint8_t todlow; 163 | uint8_t _8[0xff]; 164 | uint8_t todmid; 165 | uint8_t _9[0xff]; 166 | uint8_t todhi; 167 | uint8_t _a[0xff]; 168 | uint8_t b00; 169 | uint8_t _b[0xff]; 170 | uint8_t sdr; 171 | uint8_t _c[0xff]; 172 | uint8_t icr; 173 | uint8_t _d[0xff]; 174 | uint8_t cra; 175 | uint8_t _e[0xff]; 176 | uint8_t crb; 177 | uint8_t _f[0xff]; 178 | }; 179 | 180 | #define CIAAPRA_OVL 0x01 181 | #define CIAAPRA_LED 0x02 182 | #define CIAAPRA_CHNG 0x04 183 | #define CIAAPRA_WPRO 0x08 184 | #define CIAAPRA_TK0 0x10 185 | #define CIAAPRA_RDY 0x20 186 | #define CIAAPRA_FIR0 0x40 187 | #define CIAAPRA_FIR1 0x80 188 | 189 | #define CIABPRB_STEP 0x01 190 | #define CIABPRB_DIR 0x02 191 | #define CIABPRB_SIDE 0x04 192 | #define CIABPRB_SEL0 0x08 193 | #define CIABPRB_SEL1 0x10 194 | #define CIABPRB_SEL2 0x20 195 | #define CIABPRB_SEL3 0x40 196 | #define CIABPRB_MTR 0x80 197 | 198 | #define CIAICR_TIMER_A 0x01 199 | #define CIAICR_TIMER_B 0x02 200 | #define CIAICR_TOD 0x04 201 | #define CIAICR_SERIAL 0x08 202 | #define CIAICR_FLAG 0x10 203 | #define CIAICR_SETCLR 0x80 204 | 205 | #define CIACRA_START 0x01 206 | #define CIACRA_PBON 0x02 207 | #define CIACRA_OUTMODE 0x04 208 | #define CIACRA_RUNMODE 0x08 209 | #define CIACRA_LOAD 0x10 210 | #define CIACRA_INMODE 0x20 211 | #define CIACRA_SPMODE 0x40 212 | 213 | #define CIACRB_START 0x01 214 | #define CIACRB_PBON 0x02 215 | #define CIACRB_OUTMODE 0x04 216 | #define CIACRB_RUNMODE 0x08 217 | #define CIACRB_LOAD 0x10 218 | #define CIACRB_INMODE 0x60 219 | #define CIACRB_ALARM 0x80 220 | 221 | #define DMA_AUD0EN 0x0001 222 | #define DMA_AUD1EN 0x0002 223 | #define DMA_AUD2EN 0x0004 224 | #define DMA_AUD3EN 0x0008 225 | #define DMA_AUDxEN 0x000f /* all channels */ 226 | #define DMA_DSKEN 0x0010 227 | #define DMA_SPREN 0x0020 228 | #define DMA_BLTEN 0x0040 229 | #define DMA_COPEN 0x0080 230 | #define DMA_BPLEN 0x0100 231 | #define DMA_DMAEN 0x0200 232 | #define DMA_BLTPRI 0x0400 233 | #define DMA_BZERO 0x2000 234 | #define DMA_BBUSY 0x4000 235 | #define DMA_SETCLR 0x8000 236 | 237 | #define INT_SER_TX 0x0001 238 | #define INT_DSKBLK 0x0002 239 | #define INT_SOFT 0x0004 240 | #define INT_CIAA 0x0008 241 | #define INT_COPPER 0x0010 242 | #define INT_VBLANK 0x0020 243 | #define INT_BLIT 0x0040 244 | #define INT_AUD0 0x0080 245 | #define INT_AUD1 0x0100 246 | #define INT_AUD2 0x0200 247 | #define INT_AUD3 0x0400 248 | #define INT_SER_RX 0x0800 249 | #define INT_DSKSYN 0x1000 250 | #define INT_CIAB 0x2000 251 | #define INT_INTEN 0x4000 252 | #define INT_SETCLR 0x8000 253 | 254 | /* 255 | * Local variables: 256 | * mode: C 257 | * c-file-style: "Linux" 258 | * c-basic-offset: 4 259 | * tab-width: 4 260 | * indent-tabs-mode: nil 261 | * End: 262 | */ 263 | -------------------------------------------------------------------------------- /attic/file_loader.asm: -------------------------------------------------------------------------------- 1 | mfm_bytes equ $3200 2 | 3 | loc_cylinder equ 0 4 | loc_track equ 1 5 | 6 | movem.l d0-a6,-(sp) 7 | lea ($BFD100).l,a5 8 | bsr motors_off 9 | lea unk_7EA93(pc),a6 10 | andi.b #$7F,(a5) 11 | move.b (a6)+,d0 12 | move.l a0,2(a6) 13 | st 6(a6) 14 | and.b d0,(a5) 15 | move.w #$370,d0 16 | bsr.w load_sector 17 | movea.l a1,a2 18 | 19 | loc_7E8AE: 20 | tst.b (a2)+ 21 | bne.s loc_7E8AE 22 | suba.l a1,a2 23 | subq.w #1,a2 24 | move.l a2,d2 25 | moveq #0,d3 26 | move.l d2,d4 27 | move.l d4,d6 28 | movea.l a1,a3 29 | 30 | loc_7E8C0: 31 | mulu.w #$D,d2 32 | move.b (a1)+,d3 33 | cmpi.b #$61,d3 ; 'a' 34 | bcs.s loc_7E8D6 35 | cmpi.b #$7A,d3 ; 'z' 36 | bhi.s loc_7E8D6 37 | subi.b #$20,d3 38 | 39 | loc_7E8D6: 40 | add.w d3,d2 41 | andi.w #$7FF,d2 42 | subq.w #1,d4 43 | bne.s loc_7E8C0 44 | divu.w #$48,d2 45 | swap d2 46 | addq.w #6,d2 47 | lsl.w #2,d2 48 | move.l (a0,d2.w),d0 49 | 50 | loc_7E8EE: 51 | bsr.w load_sector 52 | lea $1B0(a0),a1 53 | cmp.b (a1)+,d6 54 | bne.s loc_7E93A 55 | movea.l a3,a2 56 | move.w d6,d0 57 | 58 | loc_7E8FE: 59 | cmpm.b (a1)+,(a2)+ 60 | bne.s loc_7E93A 61 | subq.w #1,d0 62 | bne.s loc_7E8FE 63 | move.l $144(a0),d0 64 | add.l dword_7EA96(pc),d0 65 | move.l d0,6(a6) 66 | 67 | loc_7E912: 68 | move.l $10(a0),d0 69 | beq.s loc_7E940 70 | bsr.w load_sector 71 | lea $18(a0),a1 72 | movea.l dword_7EA96(pc),a2 73 | move.l dword_7EA9A(pc),d0 74 | move.w #$1E7,d7 75 | 76 | loc_7E92C: 77 | move.b (a1)+,(a2)+ 78 | cmpa.l d0,a2 79 | dbeq d7,loc_7E92C 80 | move.l a2,2(a6) 81 | bra.s loc_7E912 82 | 83 | loc_7E93A: 84 | move.l $1F0(a0),d0 85 | bne.s loc_7E8EE 86 | 87 | loc_7E940: 88 | bsr.s motors_off 89 | movem.l (sp)+,d0-a6 90 | rts 91 | 92 | motors_off: 93 | ori.b #$F8,(a5) 94 | andi.b #$87,(a5) 95 | ori.b #$78,(a5) 96 | rts 97 | 98 | _step_one_out: 99 | bset d7,(a5) ; seek outwards (bset #1,bfd100) 100 | bsr step_one 101 | _seek_cyl0: 102 | btst #4,$F01(a5) 103 | bne _step_one_out 104 | sf (a6) ; loc_cylinder(a6) = 0 105 | 106 | seek_cylinder: 107 | tst.b (a6) ; loc_cylinder(a6) < 0? 108 | bmi _seek_cyl0 ; resync heads if so 109 | .check_cyl: 110 | cmp.b (a6),d2 111 | beq wait_dskrdy ; current cyl is correct: bail 112 | bcc .seek_inward ; current cyl too low: seek inward 113 | bset d7,(a5) 114 | subq.b #1,(a6) 115 | bra .seek_outward 116 | .seek_inward: 117 | bclr d7,(a5) 118 | addq.b #1,(a6) 119 | .seek_outward: 120 | bsr step_one 121 | bra .check_cyl 122 | 123 | step_one: 124 | bclr d3,(a5) 125 | mulu.w d3,d3 126 | bset d3,(a5) ; step pulse 127 | move.b d3,$500(a5) 128 | move.b #$10,$600(a5) 129 | move.b #$19,$E00(a5) ; CIA delay 130 | .wait_cia: 131 | btst d3,$E00(a5) 132 | bne .wait_cia 133 | 134 | wait_dskrdy: 135 | btst #5,$F01(a5) 136 | bne wait_dskrdy 137 | rts 138 | 139 | ; d0 = sector #, a1 = dest 140 | load_sector: 141 | moveq #0,d3 142 | moveq #1,d7 143 | moveq #2,d5 144 | movea.l #mfmbuff,a4 145 | move.l d0,d2 146 | ext.l d2 147 | divu.w #$B,d2 148 | move.l d2,d4 149 | swap d4 150 | cmp.b loc_track(a6),d2 151 | beq _decode_mfm 152 | move.b d2,loc_track(a6) 153 | bset d5,(a5) 154 | btst d3,d2 155 | beq .side0 156 | bclr d5,(a5) 157 | .side0: lsr.w #1,d2 158 | bsr seek_cylinder 159 | move.b #5,-2(a6) 160 | _fail_retry: 161 | subq.b #1,-2(a6) 162 | bne.s _read_mfm 163 | moveq #-1,d2 164 | move.w d2,(a6) 165 | bra.s load_sector 166 | _read_mfm: 167 | movea.l #mfmbuff,a4 168 | lea ($DFF020).l,a0 169 | move.l a4,(a0)+ ; dskpt 170 | move.w #$8210,$72(a0) ; dmacon -- enable disk dma 171 | move.l #$27F00,$78(a0) ; clear intreq & adkcon 172 | move.w #$9500,$7A(a0) ; adkcon -- MFM, wordsync 173 | move.w #$4489,$5A(a0) ; sync 4489 174 | move.w #$8000+mfm_bytes/2,(a0) 175 | move.w #$8000+mfm_bytes/2,(a0) ; dsklen -- 0x1900 words 176 | move.l #$A00000,d7 177 | .wait_dma: 178 | subq.l #1,d7 179 | beq _fail_retry 180 | btst #1,-5(a0) ; intreqr -- disk dma done? 181 | beq .wait_dma 182 | move.w #$4000,(a0) ; dsklen -- no more dma 183 | 184 | ; d4.w = sector # 185 | _decode_mfm: 186 | lea mfm_bytes-$438(a4),a2 187 | move.l #$55555555,d5 188 | .next_sector: 189 | cmpa.l a4,a2 190 | bmi _fail_retry 191 | cmpi.w #$4489,(a4)+ 192 | bne .next_sector 193 | cmpi.w #$4489,(a4) 194 | beq .next_sector 195 | movem.l (a4),d2-d3 196 | bsr decode_mfm_long 197 | lsr.w #8,d2 ; d2.w = sector # 198 | cmp.w d4,d2 199 | beq .sector_found 200 | lea.l $438(a4),a4 ; skip this sector 201 | bra .next_sector 202 | .sector_found: 203 | swap d2 ; d2.b = track # 204 | cmp.b loc_track(a6),d2 205 | bne _fail_retry ; wrong track?! 206 | lea $30(a4),a4 207 | move.l (a4)+,d4 208 | move.l (a4)+,d3 209 | eor.l d3,d4 ; d4.l = data checksum 210 | moveq #$7F,d7 211 | .next_data_long: 212 | move.l $200(a4),d3 213 | move.l (a4)+,d2 214 | eor.l d2,d4 215 | eor.l d3,d4 216 | bsr decode_mfm_long 217 | move.l d2,(a1)+ 218 | dbf d7,.next_data_long 219 | and.l d5,d4 220 | bne _fail_retry 221 | rts 222 | 223 | ; d2 = decode_mfm_long(d2 = odd, d3 = even, d5 = 0x55555555) 224 | decode_mfm_long: 225 | and.l d5,d2 226 | and.l d5,d3 227 | add.l d2,d2 228 | or.l d3,d2 229 | rts 230 | 231 | dc.b 5 232 | unk_7EA93: dc.b $F7 233 | dc.b $FF 234 | dc.b $FF 235 | dword_7EA96: dc.l $ffffffff 236 | dword_7EA9A: dc.l $ffffffff 237 | mfmaddr: dc.l $0 238 | filename: dc.b "TEST",0 239 | even 240 | mfmbuff: 241 | loadbuff: 242 | 243 | -------------------------------------------------------------------------------- /testkit/testkit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * testkit.h 3 | * 4 | * Amiga Tests: 5 | * - Memory 6 | * - Keyboard 7 | * - Floppy Drive 8 | * - Joystick / Mouse 9 | * - Audio 10 | * - Video 11 | * - CIA Timers 12 | * - Serial / Parallel 13 | * 14 | * Written & released by Keir Fraser 15 | * 16 | * This is free and unencumbered software released into the public domain. 17 | * See the file COPYING for more details, or visit . 18 | */ 19 | 20 | 21 | /******************* 22 | * AMIGA MEMORY MAP 23 | */ 24 | 25 | static volatile struct m68k_vector_table * const m68k_vec = 26 | (struct m68k_vector_table *)0x0; 27 | static volatile struct amiga_custom * const cust = 28 | (struct amiga_custom *)0xdff000; 29 | static volatile struct amiga_cia * const ciaa = 30 | (struct amiga_cia *)0x0bfe001; 31 | static volatile struct amiga_cia * const ciab = 32 | (struct amiga_cia *)0x0bfd000; 33 | 34 | /******************* 35 | * SYSTEM CONFIGURATION 36 | */ 37 | 38 | #define CHIPSET_ocs 0 39 | #define CHIPSET_ecs 1 40 | #define CHIPSET_aga 2 41 | #define CHIPSET_unknown 3 42 | extern uint8_t chipset_type; 43 | struct cpu { 44 | char name[31]; 45 | uint8_t model; /* 680[x]0 */ 46 | uint32_t pcr; /* 68060 only */ 47 | }; 48 | extern struct cpu cpu; 49 | 50 | 51 | /******************* 52 | * INTERRUPTS 53 | */ 54 | 55 | /* Write to INTREQ twice at end of ISR to prevent spurious re-entry on 56 | * A4000 with faster processors (040/060). */ 57 | #define IRQ_RESET(x) do { \ 58 | uint16_t __x = (x); \ 59 | cust->intreq = __x; \ 60 | cust->intreq = __x; \ 61 | } while (0) 62 | /* Similarly for disabling an IRQ, write INTENA twice to be sure that an 63 | * interrupt won't creep in after the IRQ_DISABLE(). */ 64 | #define IRQ_DISABLE(x) do { \ 65 | uint16_t __x = (x); \ 66 | cust->intena = __x; \ 67 | cust->intena = __x; \ 68 | } while (0) 69 | #define IRQ_ENABLE(x) do { \ 70 | uint16_t __x = INT_SETCLR | (x); \ 71 | cust->intena = __x; \ 72 | } while (0) 73 | 74 | extern volatile uint32_t spurious_autovector_total; 75 | 76 | 77 | /******************* 78 | * KICKSTART ROM 79 | */ 80 | 81 | const char *get_kick_string(void); 82 | 83 | 84 | /******************* 85 | * KEYBOARD 86 | */ 87 | 88 | /* Keyboard IRQ: Keyboard variables. */ 89 | extern volatile uint8_t keycode_buffer, do_exit; 90 | extern volatile uint8_t key_pressed[128]; 91 | 92 | /* Keycodes used for menu navigation. */ 93 | enum { 94 | K_ESC = 0x45, K_CTRL = 0x63, K_LALT = 0x64, 95 | K_F1 = 0x50, K_F2, K_F3, K_F4, K_F5, K_F6, K_F7, K_F8, K_F9, K_F10, 96 | K_HELP = 0x5f 97 | }; 98 | 99 | 100 | /******************* 101 | * DISPLAY PRINTING, DRAWING, CLEARING 102 | */ 103 | 104 | /* Regardless of intrinsic PAL/NTSC-ness, display may be 50 or 60Hz. */ 105 | extern uint8_t vbl_hz; 106 | 107 | /* Counts number of VBL IRQs. Tests may modify/reset this counter. */ 108 | extern volatile unsigned int vblank_count; 109 | 110 | /* Display size and depth. */ 111 | #define xres 640 112 | #define yres 169 113 | #define bplsz (yres*xres/8) 114 | #define planes 3 115 | 116 | /* Top-left coordinates of the display. */ 117 | #define diwstrt_h 0x81 118 | #define diwstrt_v 0x46 119 | 120 | /* Bitplane data. */ 121 | extern uint8_t *bpl[planes]; 122 | 123 | /* Print lines of text. */ 124 | struct char_row { 125 | uint8_t x, y; 126 | const char *s; 127 | }; 128 | void print_text_box(unsigned int x, unsigned int y, const char *s); 129 | void print_line(const struct char_row *r); 130 | void print_menu_nav_line(void); 131 | void text_highlight(uint16_t x, uint16_t y, uint16_t nr, int fill); 132 | 133 | /* Print a string of plain 8x8 characters straight to bitplane @b. */ 134 | void print_label(unsigned int x, unsigned int y, uint8_t b, const char *s); 135 | 136 | /* Fill and clear rectangles. Draw hollow/outline rectangles. */ 137 | void draw_rect( 138 | unsigned int x, unsigned int y, 139 | unsigned int w, unsigned int h, 140 | uint8_t plane_mask, int set); 141 | #define fill_rect(x,y,w,h,p) draw_rect(x,y,w,h,p,1) 142 | #define clear_rect(x,y,w,h,p) draw_rect(x,y,w,h,p,0) 143 | void hollow_rect( 144 | unsigned int x, unsigned int y, 145 | unsigned int w, unsigned int h, 146 | uint8_t plane_mask); 147 | 148 | /* Clear all or part of the screen. */ 149 | void clear_whole_screen(void); 150 | void clear_text_rows(uint16_t y_start, uint16_t y_nr); 151 | 152 | /* Wait for end of bitplane DMA. */ 153 | void wait_bos(void); 154 | 155 | /* Copperlist set/reset */ 156 | void copperlist_set(const void *list); 157 | void copperlist_default(void); 158 | 159 | 160 | /******************* 161 | * TIME 162 | */ 163 | 164 | /* Detected CPU frequency. CIA timers run at cpu_hz/10. */ 165 | extern unsigned int cpu_hz; 166 | 167 | /* PAL/NTSC CPU and CIA timings. */ 168 | extern uint8_t is_pal; 169 | 170 | /* Reinitialise CIAA/CIAB if they are messed with. */ 171 | void ciaa_init(void); 172 | void ciab_init(void); 173 | 174 | /* Loop to get consistent current CIA timer value. */ 175 | #define get_ciatime(_cia, _tim) ({ \ 176 | uint8_t __hi, __lo; \ 177 | do { \ 178 | __hi = (_cia)->_tim##hi; \ 179 | __lo = (_cia)->_tim##lo; \ 180 | } while (__hi != (_cia)->_tim##hi); \ 181 | ((uint16_t)__hi << 8) | __lo; }) 182 | 183 | /* Get current value of CIAATB. */ 184 | uint16_t get_ciaatb(void); 185 | 186 | /* Get number of CIA ticks since boot. */ 187 | uint32_t get_time(void); 188 | 189 | /* Tick conversion functions. */ 190 | void ticktostr(uint32_t ticks, char *s); 191 | unsigned int ms_to_ticks(uint16_t ms); 192 | 193 | /* Wait for a given number of milliseconds. */ 194 | void delay_ms(unsigned int ms); 195 | 196 | 197 | /******************* 198 | * MEMORY ALLOCATION 199 | */ 200 | 201 | /* Allocate a region of chip memory. */ 202 | void *allocmem(unsigned int sz); 203 | 204 | /* Start/end a heap arena. */ 205 | void *start_allocheap_arena(void); 206 | void end_allocheap_arena(void *p); 207 | 208 | /* List of memory regions detected by Exec. */ 209 | struct mem_region { 210 | uint16_t attr; 211 | uint32_t lower, upper; 212 | }; 213 | extern struct mem_region mem_region[]; 214 | extern uint16_t nr_mem_regions; 215 | 216 | 217 | /******************* 218 | * CANCELLATIONS 219 | */ 220 | 221 | void call_cancellable_test(int (*fn)(void *), void *arg); 222 | 223 | 224 | /******************* 225 | * DEBUG 226 | */ 227 | 228 | void init_crash_handler(void); 229 | void fixup_68000_unrecoverable_faults(void); 230 | 231 | extern char build_date[]; 232 | extern char build_time[]; 233 | extern char version[]; 234 | 235 | #define assert(_p) do { if (!(_p)) __assert_fail(); } while (0) 236 | #define __assert_fail() asm volatile ( \ 237 | "illegal \n" \ 238 | "move.w %0,%%d0 \n" \ 239 | "move.w %1,%%d0 \n" \ 240 | : : "i" (__FILE__), "i" (__LINE__) ) 241 | -------------------------------------------------------------------------------- /host_tools/hunk_loader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hunk_loader.c 3 | * 4 | * Analyse and load Amiga Hunk format executables. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #if defined(__APPLE__) && defined(__MACH__) 24 | #include 25 | #define htobe32(x) OSSwapHostToBigInt32(x) 26 | #define be32toh(x) OSSwapBigToHostInt32(x) 27 | #endif 28 | 29 | #define HUNK_HEADER 0x3F3 30 | #define HUNK_UNIT 0x3E7 31 | 32 | #define HUNK_CODE 0x3E9 33 | #define HUNK_DATA 0x3EA 34 | #define HUNK_BSS 0x3EB 35 | 36 | #define HUNK_RELOC32 0x3EC 37 | #define HUNK_RELOC32SHORT 0x3FC 38 | #define HUNK_RELOC16 0x3ED 39 | #define HUNK_RELOC8 0x3EE 40 | #define HUNK_DREL32 0x3F7 41 | #define HUNK_DREL16 0x3F8 42 | #define HUNK_DREL8 0x3F9 43 | #define HUNK_ABSRELOC16 0x3FD 44 | #define HUNK_SYMBOL 0x3F0 45 | #define HUNK_DEBUG 0x3F1 46 | #define HUNK_END 0x3F2 47 | #define HUNK_EXT 0x3EF 48 | #define HUNK_OVERLAY 0x3F5 49 | #define HUNK_BREAK 0x3F6 50 | #define HUNK_LIB 0x3FA 51 | #define HUNK_INDEX 0x3FB 52 | 53 | /* __packed: Given struct should not include ABI-compliant padding. */ 54 | #define __packed __attribute__((packed)) 55 | 56 | #define ASSERT(p) do { \ 57 | if (!(p)) errx(1, "Assertion at %u", __LINE__); } while (0) 58 | 59 | static uint32_t fetch32(char **in) 60 | { 61 | uint32_t x = be32toh(*(uint32_t *)*in); 62 | *in += 4; 63 | return x; 64 | } 65 | 66 | static void usage(int rc) 67 | { 68 | printf("Usage: hunk_loader [options] in_file out_file\n"); 69 | printf("Options:\n"); 70 | printf(" -h, --help Display this information\n"); 71 | printf(" -b, --base=N Base address for load\n"); 72 | printf(" -r, --reloc Perform relocs\n"); 73 | exit(rc); 74 | } 75 | 76 | int main(int argc, char **argv) 77 | { 78 | int ch, fd, do_reloc = 0; 79 | uint32_t hunk_id, insz, outsz, i, x, first, last; 80 | uint32_t *hunk_offs, cur = 0; 81 | char *in, *out, *p, *buf, *outbuf; 82 | uint32_t base = 0; 83 | const static char *typename[] = { "Any", "Chip", "Fast", "Reserved" }; 84 | const static char *hunkname[] = { "HUNK_CODE", "HUNK_DATA", "HUNK_BSS" }; 85 | int seen_dat; 86 | 87 | const static char sopts[] = "hb:r"; 88 | const static struct option lopts[] = { 89 | { "help", 0, NULL, 'h' }, 90 | { "base", 1, NULL, 'b' }, 91 | { "reloc", 0, NULL, 'r' }, 92 | { 0, 0, 0, 0 } 93 | }; 94 | 95 | while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { 96 | switch (ch) { 97 | case 'h': 98 | usage(0); 99 | break; 100 | case 'b': 101 | base = strtol(optarg, NULL, 16); 102 | break; 103 | case 'r': 104 | do_reloc = 1; 105 | break; 106 | default: 107 | usage(1); 108 | break; 109 | } 110 | } 111 | 112 | if (argc != (optind + 2)) 113 | usage(1); 114 | in = argv[optind]; 115 | out = argv[optind+1]; 116 | 117 | fd = open(in, O_RDONLY); 118 | if (fd == -1) 119 | err(1, "%s", in); 120 | if ((insz = lseek(fd, 0, SEEK_END)) < 0) 121 | err(1, NULL); 122 | lseek(fd, 0, SEEK_SET); 123 | if ((buf = malloc(insz)) == NULL) 124 | err(1, NULL); 125 | if (read(fd, buf, insz) != insz) 126 | err(1, NULL); 127 | close(fd); 128 | p = buf; 129 | 130 | hunk_id = fetch32(&p); 131 | if (hunk_id != HUNK_HEADER) 132 | goto bad_hunk; 133 | printf("HUNK_HEADER\n"); 134 | x = fetch32(&p); 135 | if (x) 136 | goto bad_hunk; 137 | x = fetch32(&p); 138 | first = fetch32(&p); 139 | last = fetch32(&p); 140 | if (first || (x != (last+1-first))) { 141 | /* For sanity's sake we expect only loadable hunks, numbered 0..N-1. */ 142 | printf(" Table size: %u, First: %u, Last: %u\n", x, first, last); 143 | goto bad_hunk; 144 | } 145 | hunk_offs = malloc(x * sizeof(*hunk_offs)); 146 | memset(hunk_offs, 0, x * sizeof(*hunk_offs)); 147 | hunk_offs[0] = base; 148 | for (i = first; i <= last; i++) { 149 | uint8_t type; 150 | x = fetch32(&p); 151 | type = x >> 30; 152 | x &= (1u<<30)-1; 153 | if (type >= 3) { 154 | /* We don't support extended AllocMem flags (type=3) */ 155 | printf("Bad hunk AllocFlag %u\n", type); 156 | goto bad_hunk; 157 | } 158 | printf(" Hunk %u: %u longwords (%s)\n", i, x, typename[type]); 159 | /* Real Amiga loader would AllocMem() here. */ 160 | hunk_offs[i+1] = hunk_offs[i] + 4*x; 161 | } 162 | outsz = hunk_offs[i]; 163 | outbuf = malloc(outsz); 164 | 165 | cur = seen_dat = 0; 166 | while ((p - buf) < insz) { 167 | hunk_id = fetch32(&p) & ((1u<<30)-1); 168 | switch (hunk_id) { 169 | case HUNK_CODE: 170 | case HUNK_DATA: 171 | case HUNK_BSS: 172 | if (seen_dat) 173 | cur++; 174 | seen_dat = 1; 175 | printf("\n%s [Hunk %u]\n", hunkname[hunk_id-HUNK_CODE], cur); 176 | x = fetch32(&p); 177 | printf(" %u longwords\n", x); 178 | if (hunk_id == HUNK_BSS) { 179 | memset(outbuf + hunk_offs[cur] - base, 0, 4*x); 180 | } else { 181 | memcpy(outbuf + hunk_offs[cur] - base, p, 4*x); 182 | p += 4*x; 183 | } 184 | break; 185 | case HUNK_RELOC32: { 186 | uint32_t nr, id; 187 | printf("HUNK_RELOC32\n"); 188 | while ((nr = fetch32(&p)) != 0) { 189 | id = fetch32(&p); 190 | printf(" Hunk %u: %u offsets\n", id, nr); 191 | for (i = 0; i < nr; i++) { 192 | x = fetch32(&p); 193 | if (do_reloc) { 194 | uint32_t *pp = (uint32_t *)(outbuf + hunk_offs[cur] 195 | + x - base); 196 | *pp = htobe32(be32toh(*pp) + hunk_offs[id]); 197 | } 198 | } 199 | } 200 | break; 201 | } 202 | case HUNK_END: 203 | printf("HUNK_END\n"); 204 | if (!seen_dat) { 205 | printf("Premature HUNK_END\n"); 206 | goto bad_hunk; 207 | } 208 | cur++; 209 | seen_dat = 0; 210 | break; 211 | default: 212 | printf("%08x - UNKNOWN\n", hunk_id); 213 | goto bad_hunk; 214 | } 215 | } 216 | 217 | if (cur != (last+1)) 218 | goto bad_hunk; 219 | 220 | fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644); 221 | if (fd == -1) 222 | err(1, "%s", out); 223 | if (write(fd, outbuf, outsz) != outsz) 224 | err(1, NULL); 225 | close(fd); 226 | 227 | return 0; 228 | 229 | bad_hunk: 230 | printf("ERROR_BAD_HUNK\n"); 231 | return 1; 232 | } 233 | 234 | /* 235 | * Local variables: 236 | * mode: C 237 | * c-file-style: "Linux" 238 | * c-basic-offset: 4 239 | * tab-width: 4 240 | * indent-tabs-mode: nil 241 | * End: 242 | */ 243 | -------------------------------------------------------------------------------- /testkit/crash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crash.c 3 | * 4 | * Crash handler for unexpected exceptions. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #include "testkit.h" 13 | 14 | const static char * const _exc_str[] = { 15 | [ 2] = "Bus Error", 16 | [ 3] = "Address Error", 17 | [ 4] = "Illegal Instruction", 18 | [ 5] = "Zero Divide", 19 | [ 6] = "CHK/CHK2", 20 | [ 7] = "TRAPcc", 21 | [ 8] = "Privilege Violation", 22 | [ 9] = "Trace", 23 | [10] = "Line A", 24 | [11] = "Line F", 25 | [13] = "Coprocessor Protocol Violation", 26 | [14] = "Format Error", 27 | [15] = "Uninitialised Interrupt", 28 | [24] = "Spurious Interrupt", 29 | [25] = "Level 1 IRQ", 30 | [26] = "Level 2 IRQ", 31 | [27] = "Level 3 IRQ", 32 | [28] = "Level 4 IRQ", 33 | [29] = "Level 5 IRQ", 34 | [30] = "Level 6 IRQ", 35 | [31] = "NMI", 36 | }; 37 | 38 | static const char * const exc_str(unsigned int exc_nr) 39 | { 40 | if ((exc_nr >= ARRAY_SIZE(_exc_str)) || (_exc_str[exc_nr] == NULL)) 41 | return "Unknown"; 42 | return _exc_str[exc_nr]; 43 | } 44 | 45 | static uint16_t copper[] = { 46 | 0x0100, 0x9200, /* bplcon0: 1 bitplane, hires */ 47 | 0x0180, 0x0000, /* col00, black */ 48 | 0x0182, 0x0ccc, /* col01, white */ 49 | 0xffff, 0xfffe, 50 | }; 51 | 52 | void double_crash(void); 53 | asm ( 54 | "double_crash: \n" 55 | " move.w #0x700,0xdff180 \n" 56 | " jra double_crash \n" 57 | ); 58 | 59 | /* Common entry point for unexpected exceptions. */ 60 | void common(void); 61 | asm ( 62 | "common: \n" 63 | " ori.w #0x700,%sr \n" 64 | " movem.l %d0-%d7/%a0-%a6,-(%sp) \n" 65 | " move.l %usp,%a0 \n" 66 | " move.l %a0,-(%sp) \n" 67 | " move.l %sp,%a0 \n" 68 | " move.l %a0,-(%sp) \n" 69 | " jbsr crash \n" 70 | ); 71 | 72 | /* Special unrecoverable-fault shim handlers for 68000 only. See below. */ 73 | void address_fault_68000(void); 74 | asm ( 75 | "address_fault_68000: \n" 76 | " addq.l #8,%sp \n" /* discard top of stack */ 77 | " dc.w 0x4ef9,0,0 \n" /* jump to main handler */ 78 | ); 79 | void bus_fault_68000(void); 80 | asm ( 81 | "bus_fault_68000: \n" 82 | " addq.l #8,%sp \n" /* discard top of stack */ 83 | " dc.w 0x4ef9,0,0 \n" /* jump to main handler */ 84 | ); 85 | 86 | /* Per-vector entry points, 2 words per vector: BSR.w . 87 | * The first 3 words are a common JMP target: JMP .l */ 88 | static uint16_t vectors[2*256]; 89 | 90 | /* Crash exception frame. */ 91 | struct frame { 92 | uint32_t usp; 93 | uint32_t d[8], a[7]; 94 | uint32_t vector_pc; 95 | uint16_t sr; 96 | uint32_t pc; 97 | }; 98 | 99 | /* Fix up one 68000 unrecoverable fault handler. */ 100 | static void fixup_68000(void *new_fn, volatile uint32_t *vec) 101 | { 102 | volatile uint32_t *_vec = arrayptr_launder(vec); 103 | uint32_t old_fn = *_vec; 104 | /* Search for the JMP instruction in the shim handler, and patch it. */ 105 | uint16_t *p = new_fn; 106 | while (*p != 0x4ef9) p++; 107 | *(uint32_t *)(p+1) = old_fn; 108 | /* Install our shim handler. */ 109 | *_vec = (uint32_t)new_fn; 110 | } 111 | 112 | /* 68000 (only) has weird stack formats for unrecoverable faults. These cause 113 | * us to print garbage in our crash handler. Fix this by inserting shim 114 | * handlers which discard the extra stuff at the top of the stack. */ 115 | void fixup_68000_unrecoverable_faults(void) 116 | { 117 | fixup_68000(address_fault_68000, &m68k_vec->address_error.x); 118 | fixup_68000(bus_fault_68000, &m68k_vec->bus_error.x); 119 | } 120 | 121 | void init_crash_handler(void) 122 | { 123 | unsigned int i; 124 | uint16_t *v, **pv; 125 | 126 | /* Build common absolute JMP instruction shared by all vectors. */ 127 | v = vectors; 128 | *v++ = 0x4ef9; /* JMP (common).L */ 129 | *(uint32_t *)v = (uint32_t)common; 130 | v += 3; 131 | 132 | /* Poke all exception vectors, skipping reset PC/SP. The single unique 133 | * per-vector instruction is a BSR.W which is an efficient way to stack 134 | * a value allowing us to identify the vector number. */ 135 | pv = (uint16_t **)NULL + 2; 136 | for (i = 2; i < 256; i++) { 137 | *pv++ = v; /* Set the exception vector */ 138 | *v++ = 0x6100; /* BSR.W */ 139 | *v = (uint16_t)((uint32_t)vectors - (uint32_t)v); 140 | v++; 141 | } 142 | } 143 | 144 | /* Print a string at text location (x,y) in the bitplane. */ 145 | static void print(uint16_t x, uint16_t y, const char *s) 146 | { 147 | x *= 8; 148 | y *= 10; 149 | print_label(x, y, 0, s); 150 | } 151 | 152 | /* C entry point for an unexpected exception. */ 153 | static void crash(struct frame *f) attribute_used; 154 | static void crash(struct frame *f) 155 | { 156 | uint32_t sp, ssp; 157 | uint16_t *_sp, exc_nr; 158 | unsigned int i, x, y; 159 | char s[80], src[40]; 160 | void (**pv)(void); 161 | 162 | /* Rewrite all exception vectors to avoid reentering this function should 163 | * it crash. */ 164 | pv = (void (**)(void))NULL + 2; 165 | for (i = 2; i < 256; i++) 166 | *pv++ = double_crash; 167 | 168 | /* Stop all old activity and install a simple copper with a single clear 169 | * bitplane. Wait for vblank before disabling sprites to avoid garbage. */ 170 | cust->intena = 0x7fff; 171 | cust->intreq = INT_VBLANK; 172 | while (!(cust->intreqr & INT_VBLANK)) 173 | continue; 174 | cust->dmacon = 0x7fff; 175 | cust->cop2lc.p = copper; 176 | memset(bpl[0], 0, bplsz); 177 | cust->dmacon = DMA_SETCLR | DMA_DMAEN | DMA_COPEN | DMA_BPLEN; 178 | 179 | /* Print a banner. */ 180 | x = 4; 181 | y = 0; 182 | sprintf(s, "Amiga Test Kit %s (build: %s %s)", 183 | version, build_date, build_time); 184 | print(x, y, s); 185 | 186 | /* Calculate stack pointers. */ 187 | ssp = (uint32_t)(f+1); 188 | sp = (f->sr & 0x2000) ? ssp : f->usp; 189 | 190 | /* Calculate exception vector number from vector PC. */ 191 | exc_nr = ((f->vector_pc - (uint32_t)vectors) >> 2) - 1; 192 | 193 | /* An assertion failure tells us which line of source code failed. */ 194 | if (/* illegal opcode vector */ 195 | (exc_nr == 4) 196 | /* sensible program counter */ 197 | && (f->pc > (uint32_t)_start) 198 | && (f->pc < (uint32_t)_end) 199 | && !(f->pc & 1) 200 | /* illegal ; move.w #,%d0 ; move.w #,%d0 */ 201 | && (*(uint32_t *)f->pc == 0x4afc303c)) { 202 | sprintf(src, " (%s:%u)", 203 | (char *)(uint32_t)((uint16_t *)f->pc)[2], 204 | ((uint16_t *)f->pc)[4]); 205 | } else { 206 | /* No source-code information to print. */ 207 | src[0] = '\0'; 208 | } 209 | 210 | /* Print the exception stack frame. */ 211 | y += 2; 212 | sprintf(s, "Exception #%02x (%u: %s)", 213 | exc_nr, exc_nr, exc_str(exc_nr)); 214 | print(x, y, s); 215 | x += 2; 216 | y++; 217 | sprintf(s, "PC: %08x%s", f->pc, src); 218 | print(x, y, s); 219 | y++; 220 | sprintf(s, "d0: %08x d1: %08x d2: %08x d3: %08x", 221 | f->d[0], f->d[1], f->d[2], f->d[3]); 222 | print(x, y, s); 223 | y++; 224 | sprintf(s, "d4: %08x d5: %08x d6: %08x d7: %08x", 225 | f->d[4], f->d[5], f->d[6], f->d[7]); 226 | print(x, y, s); 227 | y++; 228 | sprintf(s, "a0: %08x a1: %08x a2: %08x a3: %08x", 229 | f->a[0], f->a[1], f->a[2], f->a[3]); 230 | print(x, y, s); 231 | y++; 232 | sprintf(s, "a4: %08x a5: %08x a6: %08x a7: %08x", 233 | f->a[4], f->a[5], f->a[6], sp); 234 | print(x, y, s); 235 | y++; 236 | sprintf(s, "sr: %04x ssp: %08x usp: %08x", f->sr, ssp, f->usp); 237 | print(x, y, s); 238 | 239 | /* Print the crashed stack. */ 240 | x -= 2; 241 | y += 2; 242 | sprintf(s, "Stack Trace:"); 243 | print(x, y, s); 244 | x += 2; 245 | _sp = (uint16_t *)(sp&~1); 246 | for (i = 0; i < 6; i++) { 247 | y++; 248 | sprintf(s, "%08p: %04x %04x %04x %04x %04x %04x %04x %04x", _sp, 249 | _sp[0], _sp[1], _sp[2], _sp[3], 250 | _sp[4], _sp[5], _sp[6], _sp[7]); 251 | print(x, y, s); 252 | _sp += 8; 253 | } 254 | 255 | /* We're done, forever. */ 256 | for (;;) ; 257 | } 258 | -------------------------------------------------------------------------------- /base/init.S: -------------------------------------------------------------------------------- 1 | /* 2 | * init.S 3 | * 4 | * Common startup/entry code 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #define EXEC_Supervisor -0x1e 13 | #define EXEC_CacheClearU -0x27c 14 | #define EXEC_CacheControl -0x288 15 | 16 | #ifdef DETECT_MEMORY 17 | /* Walk Exec memory list to find all memory regions. */ 18 | move.l 4,a6 19 | move.l 0x142(a6),a0 /* ExecBase->MemList.lh_Head */ 20 | lea.l start(pc),a1 21 | move.l a1,a2 22 | add.l #mem_region-start,a1 23 | add.l #nr_mem_regions-start,a2 24 | move.w (a2),d0 /* d0.w = max # regions */ 25 | .mem: /* First check mh_Attributes specifies some valid flags: at least one 26 | * of MEMF_PUBLIC, MEMF_CHIP, or MEMF_FAST. This fixes memory detection 27 | * with AROS which includes some dummy regions in the MemList. */ 28 | move.b 15(a0),d1 /* mh_Attributes */ 29 | and.b #0x7,d1 /* MEMF_PUBLIC|MEMF_CHIP|MEMF_FAST */ 30 | jeq 1f /* Skip this chunk if none of the above */ 31 | move.w 14(a0),(a1)+ /* mh_Attributes */ 32 | /* A second sanity check: is mh_Lower < mh_Upper? */ 33 | move.l 20(a0),d1 34 | cmp.l 24(a0),d1 /* mh_Lower < mh_Upper?... */ 35 | jcc 1f /* ...skip if not */ 36 | /* Copy this region into our own region list. */ 37 | move.l d1,(a1)+ /* mh_Lower */ 38 | move.l 24(a0),(a1)+ /* mh_Upper */ 39 | subq.w #1,d0 /* #regions-- */ 40 | jeq 2f /* done if we can fit no more regions */ 41 | 1: move.l (a0),a0 /* ln_Succ */ 42 | tst.l (a0) /* ... != NULL? */ 43 | jne .mem 44 | 2: sub.w d0,(a2) /* update nr_mem_regions with actual # */ 45 | #endif 46 | 47 | /* Disable caches if possible, including flush. */ 48 | cmp.w #37,0x14(a6) /* exec.lib_version >= 37 */ 49 | jcs .no_cache_disable 50 | moveq #0,d0 51 | moveq #-1,d1 52 | jsr EXEC_CacheControl(a6) 53 | .no_cache_disable: 54 | 55 | /* a4 = current VBR */ 56 | sub.l a4,a4 57 | btst.b #0,297(a6) /* check for 68010+ in AttnFlags */ 58 | jeq .novbr /* If a mere 68000 then there is no VBR */ 59 | lea getvbr(pc),a5 60 | jsr EXEC_Supervisor(a6) 61 | .novbr: 62 | 63 | /* Initialise custom chips */ 64 | lea.l (0xdff000).l,a6 65 | move.w #0x7fff,d0 66 | move.w d0,0x9a(a6) /* intena = 0 */ 67 | move.w d0,0x9c(a6) /* intreq = 0 */ 68 | move.w d0,0x96(a6) /* dmacon = 0 */ 69 | move.w d0,0x9e(a6) /* adkcon = 0 */ 70 | move.w #0x8200,0x96(a6) /* enable master DMA */ 71 | move.w #0xc000,0x9a(a6) /* enable master IRQ */ 72 | moveq #0,d0 73 | move.w d0,0x180(a6) /* color0 = black */ 74 | 75 | /* Clobber ExecBase. We are going to take over memory and Kickstart 76 | * cannot rely on the Exec memory lists when it restarts. Make ExecBase 77 | * an odd address as that is guaranteed to fail the restart checks. */ 78 | not.l (4).w 79 | 80 | /* Floppy motors off */ 81 | lea (0xbfd100).l,a5 82 | ori.b #0xf8,(a5) 83 | andi.b #0x87,(a5) 84 | ori.b #0x78,(a5) 85 | 86 | /* Force supervisor mode */ 87 | lea.l .priv(pc),a0 88 | move.l a0,0x20(a4) 89 | .priv: move.w #0x2700,sr /* SR = 0x2700 (supervisor mode, no irqs) */ 90 | 91 | /* Skip faulting instruction on Illegal and Line F exceptions */ 92 | lea.l trap_skip(pc),a0 93 | move.l a0,(0x10).w /* Illegal */ 94 | move.l a0,(0x2c).w /* Line F */ 95 | 96 | /* Disable caches (Note: d0.l = 0) */ 97 | dc.l 0x4e7b0801 /* movec.l d0,vbr */ 98 | tst.b d0 /* set CCR.ZF */ 99 | dc.l 0x4e7a1004 /* movec.l itt0,d1 */ /* 68040+ only */ 100 | jeq .040 /* CCR.ZF iff 040/060 */ 101 | 102 | /* Disable 020/030 caches */ 103 | tst.b d0 /* set CCR.ZF */ 104 | dc.l 0x4e7b0002 /* movec.l d0,cacr */ 105 | jne .done /* CCR.ZF iff 020/030: Bail on 000/010 */ 106 | 107 | /* Detect 020 vs 030: Does CACR implement bit 9? */ 108 | move.l #1<<9,d1 109 | dc.l 0x4e7b1002 /* movec.l d1,cacr */ 110 | dc.l 0x4e7a1002 /* movec.l cacr,d1 */ 111 | tst.w d1 /* d1=0 iff running on 68020 */ 112 | jeq .done /* Bail if 68020 */ 113 | 114 | .030: /* Disable 030 MMU */ 115 | dc.l 0xf0174200 /* pmove tc,(sp) */ 116 | clr.b (sp) /* clear TC.{E,SRE,FCL} */ 117 | dc.l 0xf0174000 /* pmove (sp),tc */ 118 | jra .done 119 | 120 | .040: /* Disable 040/060 caches and superscalar dispatch */ 121 | dc.l 0x4e7a1002 /* movec.l cacr,d1 */ 122 | tst.l d1 /* Bit 31 set? (68040+ Data Cache Enabled) */ 123 | jpl 1f /* Skip CPUSHA if not */ 124 | dc.l 0xf4784e71 /* cpusha dc */ /* 68040+ only */ 125 | 1: dc.l 0x4e7b0002 /* movec.l d0,cacr */ 126 | dc.l 0x4e7b0808 /* movec.l d0,pcr */ /* 68060 only */ 127 | /* Disable 040/060 MMU */ 128 | dc.l 0x4e7b0003 /* movec.l d0,tc */ 129 | dc.l 0x4e7b0004 /* movec.l d0,itt0 */ 130 | dc.l 0x4e7b0005 /* movec.l d0,itt1 */ 131 | dc.l 0x4e7b0006 /* movec.l d0,dtt0 */ 132 | dc.l 0x4e7b0007 /* movec.l d0,dtt1 */ 133 | 134 | /* Initialise stack pointers. 135 | * *** DO NOT USE THE STACK UNTIL AFTER WE ARE RELOCATED!! *** */ 136 | .done: lea.l (SUPER_SP).l,sp /* SSP */ 137 | lea.l (USER_SP).l,a0 138 | move.l a0,usp /* USP */ 139 | 140 | /* Check whether our init code overlaps with its final destination. 141 | * Since the final destination is as low as possible in memory, this 142 | * can only occur by the end of the destination running into the start 143 | * of the current location. */ 144 | lea.l start(pc),a0 145 | move.l a0,d0 /* d0 = current location */ 146 | move.l #estart,d1 /* d1 = end of destination */ 147 | cmp.l d1,d0 /* Does the destination overlap with us? */ 148 | jcc 2f 149 | 150 | /* It does overlap so shuffle the entire payload upwards. 151 | * This is safe because we are so low in memory there is guaranteed 152 | * to be enough memory beyond us to copy into. If we were high enough 153 | * in memory for this to be a problem we would not be overlapping 154 | * with the final destination in the first place. We copy backwards 155 | * because the shuffle destination overlaps with us. */ 156 | lea.l estart(pc),a1 /* a1 = destination */ 157 | move.l #_sbss-start,d0 /* d0 = #bytes to copy */ 158 | add.l d0,a0 159 | add.l d0,a1 160 | lsr.l #2,d0 161 | subq.l #1,d0 162 | 1: move.l -(a0),-(a1) /* backwards copy */ 163 | dbf d0,1b 164 | move.l a1,a0 /* our dest is the next copy's source */ 165 | jmp 2f-start(a1) 166 | 167 | 2: /* Copy the init code only to final destination. We will copy the rest 168 | * of the payload using a further copy loop, executing from the final 169 | * destination. */ 170 | move.l #start,a1 171 | lea.l 2f-start(a1),a2 /* a2 = jump target */ 172 | move.l #estart-start,d0 /* d0 = #bytes = init code only */ 173 | lsr.l #2,d0 174 | subq.l #1,d0 175 | 1: move.l (a0)+,(a1)+ 176 | dbf d0,1b 177 | jmp (a2) 178 | 179 | 2: /* NOW EXECUTING INIT CODE AT THE FINAL DESTINATION. 180 | * We now copy the rest of the payload. Copy pointers are already 181 | * initialised for us. Calculate new length and do the copy. */ 182 | move.l #_sbss-estart,d0 183 | lsr.l #2,d0 184 | subq.l #1,d0 185 | 1: move.l (a0)+,(a1)+ 186 | dbf d0,1b 187 | 188 | /* Allow CPU interrupts now that we are definitely executing clear 189 | * of the stack, and return to user mode. */ 190 | move.w #0x0000,sr 191 | 192 | /* Jump to C code. */ 193 | jmp (cstart).l 194 | 195 | getvbr: dc.l 0x4e7ac801 /* movec.l vbr,a4 */ 196 | rte 197 | 198 | trap_skip: 199 | and.w #~4,(sp) /* clear CCR_ZF */ 200 | addq.l #4,2(sp) /* skip faulting instruction */ 201 | rte 202 | 203 | .balign 4 204 | estart: 205 | -------------------------------------------------------------------------------- /host_tools/kickconv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kickconv.c 3 | * 4 | * Byte-swap/split/dupe/decrypt Kickstart ROM files for EPROM programming. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #if defined(__APPLE__) && defined(__MACH__) 24 | #include 25 | #define htobe32(x) OSSwapHostToBigInt32(x) 26 | #define be32toh(x) OSSwapBigToHostInt32(x) 27 | #endif 28 | 29 | static uint16_t _swap(uint16_t x) 30 | { 31 | return (x >> 8) | (x << 8); 32 | } 33 | 34 | static void swap(void *buf, int sz) 35 | { 36 | int i; 37 | uint16_t *p = buf; 38 | for (i = 0; i < sz/2; i++, p++) 39 | *p = _swap(*p); 40 | } 41 | 42 | static uint32_t checksum(void *dat, unsigned int len) 43 | { 44 | uint32_t csum = 0, *p = dat; 45 | unsigned int i; 46 | for (i = 0; i < len/4; i++) { 47 | uint32_t x = be32toh(p[i]); 48 | if ((csum + x) < csum) 49 | csum++; 50 | csum += x; 51 | } 52 | return ~csum; 53 | } 54 | 55 | static void usage(int rc) 56 | { 57 | printf("Usage: kickconv [options] in_file out_file\n"); 58 | printf("Options:\n"); 59 | printf(" -h, --help Display this information\n"); 60 | printf(" -c, --csum Fix bad ROM checksum\n"); 61 | printf(" -i, --cd32-swizz CD32-ROM swizzle\n"); 62 | printf(" -I, --cd32-deswizz CD32-ROM de-swizzle\n"); 63 | printf(" -k, --key=FILE Key file for encrypted ROM\n"); 64 | printf(" -s, --swap Swap endianess (little vs big endian)\n"); 65 | printf(" -S, --split Split into two 16-bit ROM files\n"); 66 | printf(" -m, --merge Merge split ROM files into one\n"); 67 | exit(rc); 68 | } 69 | 70 | int main(int argc, char **argv) 71 | { 72 | int ch, fd, do_swap = 0, split = 0, fix_csum = 0; 73 | int insz, i, j, is_encrypted = 0; 74 | uint8_t *buf, *outbuf[2], header[11]; 75 | char *in, *out, *keyfile = NULL; 76 | uint32_t csum; 77 | enum { CD32_SWIZZLE = 1, CD32_DESWIZZLE = 2 } cd32_transform = 0; 78 | 79 | const static char sopts[] = "hciIk:sSm"; 80 | const static struct option lopts[] = { 81 | { "help", 0, NULL, 'h' }, 82 | { "csum", 0, NULL, 'c' }, 83 | { "cd32-swizz", 0, NULL, 'i' }, 84 | { "cd32-deswizz", 0, NULL, 'I' }, 85 | { "key", 1, NULL, 'k' }, 86 | { "swap", 0, NULL, 's' }, 87 | { "split", 0, NULL, 'S' }, 88 | { "merge", 0, NULL, 'm' }, 89 | { 0, 0, 0, 0 } 90 | }; 91 | 92 | while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { 93 | switch (ch) { 94 | case 'h': 95 | usage(0); 96 | break; 97 | case 'c': 98 | fix_csum = 1; 99 | break; 100 | case 'i': 101 | cd32_transform = CD32_SWIZZLE; 102 | break; 103 | case 'I': 104 | cd32_transform = CD32_DESWIZZLE; 105 | break; 106 | case 'k': 107 | keyfile = optarg; 108 | break; 109 | case 's': 110 | do_swap = 1; 111 | break; 112 | case 'S': 113 | split = 1; 114 | break; 115 | case 'm': 116 | split = -1; 117 | break; 118 | default: 119 | usage(1); 120 | break; 121 | } 122 | } 123 | 124 | if (argc != (optind + 2)) 125 | usage(1); 126 | in = argv[optind]; 127 | out = argv[optind+1]; 128 | 129 | if (split == -1) { /* merge */ 130 | char inname[256]; 131 | int _sz; 132 | uint16_t *a, *p; 133 | uint8_t *_b; 134 | snprintf(inname, sizeof(inname), "%s_hi", in); 135 | fd = open(inname, O_RDONLY); 136 | if (fd == -1) 137 | err(1, "%s", in); 138 | if ((insz = lseek(fd, 0, SEEK_END)) < 0) 139 | err(1, NULL); 140 | lseek(fd, 0, SEEK_SET); 141 | if ((_b = malloc(insz)) == NULL) 142 | err(1, NULL); 143 | if ((buf = malloc(2*insz)) == NULL) 144 | err(1, NULL); 145 | if (read(fd, _b, insz) != insz) 146 | err(1, NULL); 147 | close(fd); 148 | 149 | a = (uint16_t *)_b; 150 | p = (uint16_t *)buf; 151 | for (i = 0; i < insz/2; i++) { 152 | *p = *a++; 153 | p += 2; 154 | } 155 | 156 | snprintf(inname, sizeof(inname), "%s_lo", in); 157 | fd = open(inname, O_RDONLY); 158 | if (fd == -1) 159 | err(1, "%s", in); 160 | if ((_sz = lseek(fd, 0, SEEK_END)) < 0) 161 | err(1, NULL); 162 | if (_sz != insz) 163 | errx(1, "Hi/lo ROM pair must be same size"); 164 | lseek(fd, 0, SEEK_SET); 165 | if (read(fd, _b, insz) != insz) 166 | err(1, NULL); 167 | close(fd); 168 | 169 | a = (uint16_t *)_b; 170 | p = (uint16_t *)buf + 1; 171 | for (i = 0; i < insz/2; i++) { 172 | *p = *a++; 173 | p += 2; 174 | } 175 | 176 | free(_b); 177 | insz *= 2; 178 | 179 | } else { 180 | fd = open(in, O_RDONLY); 181 | if (fd == -1) 182 | err(1, "%s", in); 183 | if ((insz = lseek(fd, 0, SEEK_END)) < 0) 184 | err(1, NULL); 185 | lseek(fd, 0, SEEK_SET); 186 | if (insz < 8192) 187 | errx(1, "Input file too short"); 188 | if (read(fd, header, sizeof(header)) != sizeof(header)) 189 | err(1, NULL); 190 | is_encrypted = !strncmp((char *)header, "AMIROMTYPE1", sizeof(header)); 191 | if (is_encrypted) { 192 | insz -= sizeof(header); 193 | } else { 194 | lseek(fd, 0, SEEK_SET); 195 | } 196 | if ((buf = malloc(insz)) == NULL) 197 | err(1, NULL); 198 | if (read(fd, buf, insz) != insz) 199 | err(1, NULL); 200 | close(fd); 201 | } 202 | 203 | if (is_encrypted && !keyfile) 204 | errx(1, "Must specify keyfile for encrypted ROM"); 205 | if (!is_encrypted && keyfile) 206 | errx(1, "Expected encrypted ROM"); 207 | if ((insz & (insz-1)) != 0) 208 | errx(1, "Kickstart image must be power-of-two sized"); 209 | 210 | printf("Input: '%s'", in); 211 | if (do_swap) 212 | printf("; Swap"); 213 | if (split) 214 | printf("; %s", (split == -1) ? "Merge" : "Split"); 215 | if (keyfile) 216 | printf("; Decrypt(\"%s\")", keyfile); 217 | if (cd32_transform) 218 | printf("; CD32-%s", (cd32_transform == CD32_SWIZZLE) 219 | ? "Swizzle" : "Deswizzle"); 220 | printf("\n"); 221 | 222 | if (keyfile) { 223 | unsigned char *key; 224 | int keysz; 225 | fd = open(keyfile, O_RDONLY); 226 | if (fd == -1) 227 | err(1, "%s", keyfile); 228 | if ((keysz = lseek(fd, 0, SEEK_END)) < 0) 229 | err(1, NULL); 230 | lseek(fd, 0, SEEK_SET); 231 | if ((key = malloc(keysz)) == NULL) 232 | err(1, NULL); 233 | if (read(fd, key, keysz) != keysz) 234 | err(1, NULL); 235 | close(fd); 236 | for (i = j = 0; i < insz; i++, j = (j + 1) % keysz) 237 | buf[i] ^= key[j]; 238 | free(key); 239 | } 240 | 241 | if (do_swap && (split == -1)) 242 | swap(buf, insz); 243 | 244 | csum = checksum(buf, insz); 245 | printf("ROM Checksum: %s", csum ? "BAD" : "OK"); 246 | if (csum) { 247 | if (fix_csum) { 248 | *(uint32_t *)&buf[insz-24] = 0; 249 | *(uint32_t *)&buf[insz-24] = htobe32(checksum(buf, insz)); 250 | printf(" (Fixed up: now OK)"); 251 | } else { 252 | printf(" (Use option -c/--csum to fix it up)"); 253 | } 254 | } 255 | putchar('\n'); 256 | 257 | if (cd32_transform) { 258 | uint16_t *in = (uint16_t *)buf, *out = malloc(insz); 259 | if (cd32_transform == CD32_SWIZZLE) { 260 | for (i = 0; i < insz/2; i++) 261 | out[(i>>1)|((i&1)*(insz/4))] = in[i]; 262 | } else { 263 | for (i = 0; i < insz/2; i++) 264 | out[i] = in[(i>>1)|((i&1)*(insz/4))]; 265 | } 266 | free(buf); 267 | buf = (uint8_t *)out; 268 | } 269 | 270 | if (do_swap && (split != -1)) 271 | swap(buf, insz); 272 | 273 | if (split == 1) { 274 | char outname[256], *s = strrchr(out, '.'); 275 | uint16_t *a, *b, *p; 276 | a = (uint16_t *)(outbuf[0] = malloc(insz)); 277 | b = (uint16_t *)(outbuf[1] = malloc(insz)); 278 | for (j = 0; j < 2; j++) { 279 | p = (uint16_t *)buf; 280 | for (i = 0; i < insz/4; i++) { 281 | *a++ = *p++; 282 | *b++ = *p++; 283 | } 284 | } 285 | 286 | /* HI: U6A (A1200), U175 (A4000), U181 (A3000). */ 287 | if (s) { 288 | strncpy(outname, out, s-out); 289 | strcpy(outname+(s-out), "_hi"); 290 | strcat(outname, out+(s-out)); 291 | } else { 292 | snprintf(outname, sizeof(outname), "%s_hi", out); 293 | } 294 | fd = open(outname, O_WRONLY|O_CREAT|O_TRUNC, 0644); 295 | if (fd == -1) 296 | err(1, "%s", outname); 297 | if (write(fd, outbuf[0], insz) != insz) 298 | err(1, NULL); 299 | close(fd); 300 | 301 | /* LO: U6B (A1200), U176 (A4000), U180 (A3000). */ 302 | if (s) { 303 | strcpy(outname+(s-out), "_lo"); 304 | strcat(outname, out+(s-out)); 305 | } else { 306 | snprintf(outname, sizeof(outname), "%s_lo", out); 307 | } 308 | fd = open(outname, O_WRONLY|O_CREAT|O_TRUNC, 0644); 309 | if (fd == -1) 310 | err(1, "%s", outname); 311 | if (write(fd, outbuf[1], insz) != insz) 312 | err(1, NULL); 313 | close(fd); 314 | } else { 315 | fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644); 316 | if (fd == -1) 317 | err(1, "%s", out); 318 | if (write(fd, buf, insz) != insz) 319 | err(1, NULL); 320 | close(fd); 321 | } 322 | 323 | return 0; 324 | } 325 | 326 | /* 327 | * Local variables: 328 | * mode: C 329 | * c-file-style: "Linux" 330 | * c-basic-offset: 4 331 | * tab-width: 4 332 | * indent-tabs-mode: nil 333 | * End: 334 | */ 335 | -------------------------------------------------------------------------------- /testkit/keyboard.c: -------------------------------------------------------------------------------- 1 | /* 2 | * keyboard.c 3 | * 4 | * Test the standard Amiga keyboard interface. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | #include "testkit.h" 13 | 14 | /* Keyboard IRQ: Keyboard variables. */ 15 | volatile uint8_t keycode_buffer, do_exit; 16 | volatile uint8_t key_pressed[128]; 17 | /* A buffer ring for holding up to 1024 consecutive keycodes without loss. 18 | * Avoids losing key events during the keyboard test. Note no use of volatile: 19 | * make sure to use barrier() as needed to synchronise with the irq handler. */ 20 | static uint8_t keycode_ring[1024]; 21 | static uint16_t keycode_prod, keycode_cons; 22 | 23 | uint8_t keyboard_IRQ(void) 24 | { 25 | uint16_t t_s; 26 | uint8_t keycode, key; 27 | static uint8_t prev_key; 28 | 29 | /* Grab the keycode and begin handshake. */ 30 | keycode = ~ciaa->sdr; 31 | ciaa->cra |= CIACRA_SPMODE; /* start the handshake */ 32 | t_s = get_ciaatb(); 33 | 34 | /* Decode the keycode, detect Ctrl + L.Alt. */ 35 | key = (keycode >> 1) | (keycode << 7); /* ROR 1 */ 36 | if ((prev_key == K_CTRL) && (key == K_LALT)) 37 | do_exit = 1; /* Ctrl + L.Alt */ 38 | prev_key = key; 39 | 40 | /* Place key-down events in the basic keycode buffer. */ 41 | if (!(key & 0x80)) 42 | keycode_buffer = key; 43 | 44 | /* Maintain an array of which keys are currently pressed. */ 45 | key_pressed[key & 0x7f] = !(key & 0x80); 46 | 47 | /* Place all keycodes in the buffer ring if there is space. */ 48 | if ((keycode_prod - keycode_cons) != ARRAY_SIZE(keycode_ring)) 49 | keycode_ring[keycode_prod++ & (ARRAY_SIZE(keycode_ring)-1)] = key; 50 | 51 | /* Wait to finish handshake over the serial line. We wait for 65 CIA ticks, 52 | * which is approx 90us: Longer than the 85us minimum dictated by the 53 | * HRM. */ 54 | while ((uint16_t)(t_s - get_ciaatb()) < 65) 55 | continue; 56 | ciaa->cra &= ~CIACRA_SPMODE; /* finish the handshake */ 57 | 58 | return key; 59 | } 60 | 61 | /* List of keycaps and their locations, for drawing the keymap. 62 | * Array is indexed by raw keycode. */ 63 | const static struct keycap { 64 | uint16_t x, y, w, h; /* box is (x,y) to (x+w,y+h) inclusive */ 65 | const char name[4]; /* name to print on keycap */ 66 | } keymap[128] = { 67 | [0x45] = { 0, 0, 25, 15, "Esc" }, 68 | [0x50] = { 35, 0, 31, 15, "F1" }, 69 | [0x51] = { 66, 0, 31, 15, "F2" }, 70 | [0x52] = { 97, 0, 31, 15, "F3" }, 71 | [0x53] = { 128, 0, 31, 15, "F4" }, 72 | [0x54] = { 159, 0, 31, 15, "F5" }, 73 | [0x55] = { 200, 0, 31, 15, "F6" }, 74 | [0x56] = { 231, 0, 31, 15, "F7" }, 75 | [0x57] = { 262, 0, 31, 15, "F8" }, 76 | [0x58] = { 293, 0, 31, 15, "F9" }, 77 | [0x59] = { 324, 0, 31, 15, "F10" }, 78 | 79 | [0x00] = { 0, 20, 35, 15, "`" }, 80 | [0x01] = { 35, 20, 25, 15, "1" }, 81 | [0x02] = { 60, 20, 25, 15, "2" }, 82 | [0x03] = { 85, 20, 25, 15, "3" }, 83 | [0x04] = { 110, 20, 25, 15, "4" }, 84 | [0x05] = { 135, 20, 25, 15, "5" }, 85 | [0x06] = { 160, 20, 25, 15, "6" }, 86 | [0x07] = { 185, 20, 25, 15, "7" }, 87 | [0x08] = { 210, 20, 25, 15, "8" }, 88 | [0x09] = { 235, 20, 25, 15, "9" }, 89 | [0x0a] = { 260, 20, 25, 15, "0" }, 90 | [0x0b] = { 285, 20, 25, 15, "-" }, 91 | [0x0c] = { 310, 20, 25, 15, "=" }, 92 | [0x0d] = { 335, 20, 25, 15, "\\" }, 93 | [0x41] = { 360, 20, 25, 15, "BS" }, 94 | 95 | [0x42] = { 0, 35, 47, 15, "Tab" }, 96 | [0x10] = { 47, 35, 25, 15, "Q" }, 97 | [0x11] = { 72, 35, 25, 15, "W" }, 98 | [0x12] = { 97, 35, 25, 15, "E" }, 99 | [0x13] = { 122, 35, 25, 15, "R" }, 100 | [0x14] = { 147, 35, 25, 15, "T" }, 101 | [0x15] = { 172, 35, 25, 15, "Y" }, 102 | [0x16] = { 197, 35, 25, 15, "U" }, 103 | [0x17] = { 222, 35, 25, 15, "I" }, 104 | [0x18] = { 247, 35, 25, 15, "O" }, 105 | [0x19] = { 272, 35, 25, 15, "P" }, 106 | [0x1a] = { 297, 35, 25, 15, "[" }, 107 | [0x1b] = { 322, 35, 25, 15, "]" }, 108 | [0x44] = { 355, 35, 30, 30, "Ret" }, 109 | 110 | [0x63] = { 0, 50, 30, 15, "Ctl" }, 111 | [0x62] = { 30, 50, 25, 15, "CL" }, 112 | [0x20] = { 55, 50, 25, 15, "A" }, 113 | [0x21] = { 80, 50, 25, 15, "S" }, 114 | [0x22] = { 105, 50, 25, 15, "D" }, 115 | [0x23] = { 130, 50, 25, 15, "F" }, 116 | [0x24] = { 155, 50, 25, 15, "G" }, 117 | [0x25] = { 180, 50, 25, 15, "H" }, 118 | [0x26] = { 205, 50, 25, 15, "J" }, 119 | [0x27] = { 230, 50, 25, 15, "K" }, 120 | [0x28] = { 255, 50, 25, 15, "L" }, 121 | [0x29] = { 280, 50, 25, 15, ";" }, 122 | [0x2a] = { 305, 50, 25, 15, "'" }, 123 | [0x2b] = { 330, 50, 25, 15, " " }, 124 | 125 | [0x60] = { 0, 65, 40, 15, "Sh." }, 126 | [0x30] = { 40, 65, 25, 15, " " }, 127 | [0x31] = { 65, 65, 25, 15, "Z" }, 128 | [0x32] = { 90, 65, 25, 15, "X" }, 129 | [0x33] = { 115, 65, 25, 15, "C" }, 130 | [0x34] = { 140, 65, 25, 15, "V" }, 131 | [0x35] = { 165, 65, 25, 15, "B" }, 132 | [0x36] = { 190, 65, 25, 15, "N" }, 133 | [0x37] = { 215, 65, 25, 15, "M" }, 134 | [0x38] = { 240, 65, 25, 15, "," }, 135 | [0x39] = { 265, 65, 25, 15, "." }, 136 | [0x3a] = { 290, 65, 25, 15, "/" }, 137 | [0x61] = { 315, 65, 70, 15, "Sh." }, 138 | 139 | [0x64] = { 20, 80, 30, 15, "Alt" }, 140 | [0x66] = { 50, 80, 30, 15, "Am" }, 141 | [0x40] = { 80, 80, 220, 15, "Spc" }, 142 | [0x67] = { 300, 80, 30, 15, "Am" }, 143 | [0x65] = { 330, 80, 30, 15, "Alt" }, 144 | 145 | [0x46] = { 395, 20, 37, 15, "Del" }, 146 | [0x5f] = { 432, 20, 38, 15, "Hlp" }, 147 | [0x4c] = { 420, 50, 25, 15, "^" }, 148 | [0x4f] = { 395, 65, 25, 15, "<" }, 149 | [0x4d] = { 420, 65, 25, 15, "\\/" }, 150 | [0x4e] = { 445, 65, 25, 15, ">" }, 151 | 152 | [0x5a] = { 480, 20, 25, 15, "(" }, 153 | [0x5b] = { 505, 20, 25, 15, ")" }, 154 | [0x5c] = { 530, 20, 25, 15, "/" }, 155 | [0x5d] = { 555, 20, 25, 15, "*" }, 156 | [0x3d] = { 480, 35, 25, 15, "7" }, 157 | [0x3e] = { 505, 35, 25, 15, "8" }, 158 | [0x3f] = { 530, 35, 25, 15, "9" }, 159 | [0x4a] = { 555, 35, 25, 15, "-" }, 160 | [0x2d] = { 480, 50, 25, 15, "4" }, 161 | [0x2e] = { 505, 50, 25, 15, "5" }, 162 | [0x2f] = { 530, 50, 25, 15, "6" }, 163 | [0x5e] = { 555, 50, 25, 15, "+" }, 164 | [0x1d] = { 480, 65, 25, 15, "1" }, 165 | [0x1e] = { 505, 65, 25, 15, "2" }, 166 | [0x1f] = { 530, 65, 25, 15, "3" }, 167 | [0x43] = { 555, 65, 25, 30, "En" }, 168 | [0x0f] = { 480, 80, 50, 15, "0" }, 169 | [0x3c] = { 530, 80, 25, 15, "." }, 170 | }; 171 | 172 | /* Reverse-video effect for highlighting keypresses in the keymap. */ 173 | static uint16_t copper_kbd[] = { 174 | /* reverse video */ 175 | 0x0182, 0x0ddd, /* col01 = foreground */ 176 | 0x0186, 0x0222, /* col03 = shadow */ 177 | 0x0188, 0x0484, /* col04 = previously-pressed highlight */ 178 | 0x018a, 0x0ddd, /* col05 = foreground */ 179 | 0x018e, 0x0222, /* col07 = shadow */ 180 | 0x4407, 0xfffe, 181 | 0x0180, 0x0ddd, 182 | 0x4507, 0xfffe, 183 | 0x0180, 0x0402, 184 | 0xbb07, 0xfffe, 185 | /* normal video */ 186 | 0x0182, 0x0222, /* col01 = shadow */ 187 | 0x0186, 0x0ddd, /* col03 = foreground */ 188 | 0x0188, 0x04c4, /* col04 = menu-option highlight */ 189 | 0x018a, 0x0222, /* col05 = shadow */ 190 | 0x018e, 0x0ddd, /* col07 = foreground */ 191 | 0xf007, 0xfffe, 192 | 0x0180, 0x0ddd, 193 | 0xf107, 0xfffe, 194 | 0x0180, 0x0103, 195 | 0xffff, 0xfffe, 196 | }; 197 | 198 | void kbdcheck(void) 199 | { 200 | char s[80], num[5]; 201 | struct char_row r = { .x = 8, .y = 10, .s = s }; 202 | const struct keycap *cap; 203 | unsigned int i, l, x, y; 204 | 205 | copperlist_set(copper_kbd); 206 | 207 | /* Draw the keymap. This resides in bitplane 1. We then draw filled boxes 208 | * in bitplane 0 to indicate keys which are currently pressed. The reverse 209 | * video effect causes the key to be highlighted with the key name still 210 | * visible. */ 211 | hollow_rect(20, 8, 601, 106, 1<<1); 212 | for (i = 0; i < ARRAY_SIZE(keymap); i++) { 213 | cap = &keymap[i]; 214 | if (!cap->h) 215 | continue; 216 | /* Draw the outline rectangle. */ 217 | x = 30 + cap->x; 218 | y = 13 + cap->y; 219 | hollow_rect(x, y, cap->w+1, cap->h+1, 1<<1); 220 | if (i == 0x44) /* Return key is not a rectangle. Bodge it.*/ 221 | clear_rect(x, y+1, 1, 14, 1<<1); 222 | /* Drawn the name in the centre of the outline rectangle. */ 223 | for (l = 0; cap->name[l]; l++) 224 | continue; 225 | x += (cap->w+1) / 2; 226 | x -= l * 4; 227 | y += (cap->h+1) / 2; 228 | y -= 4; 229 | print_label(x, y, 1, cap->name); 230 | } 231 | 232 | /* Raw keycodes are displayed in a list at the bottom of the screen. */ 233 | sprintf(s, "Raw Keycodes:"); 234 | print_line(&r); 235 | r.y = 14; 236 | sprintf(s, "$C main menu$%21s[ATK %s]", "", version); 237 | print_line(&r); 238 | r.y = 11; 239 | 240 | i = 0; 241 | s[0] = '\0'; 242 | keycode_cons = keycode_prod; /* clear the keycode ring */ 243 | while (!do_exit) { 244 | /* Wait for a key in the keycode ring and then consume it. */ 245 | uint8_t key, setclr, bpls; 246 | barrier(); /* see updates from keyboard irq */ 247 | if (keycode_cons == keycode_prod) 248 | continue; 249 | key = keycode_ring[keycode_cons++ & (ARRAY_SIZE(keycode_ring)-1)]; 250 | 251 | /* Out of list space. Clear the keycode-list area. */ 252 | if (r.y == 14) { 253 | while (r.y > 11) { 254 | r.y--; 255 | sprintf(s, ""); 256 | print_line(&r); 257 | } 258 | } 259 | 260 | /* Append the new keycode to the current line. */ 261 | sprintf(num, "%02x ", key); 262 | strcat(s, num); 263 | print_line(&r); 264 | if (i++ == 8) { 265 | i = 0; 266 | s[0] = '\0'; 267 | r.y++; 268 | } 269 | 270 | /* Find the keycap (if any) and highlight as necessary. */ 271 | cap = &keymap[key & 0x7f]; 272 | if (!cap->h) 273 | continue; 274 | x = 30 + cap->x; 275 | y = 13 + cap->y; 276 | setclr = !(key & 0x80); 277 | bpls = setclr ? (1<<2)|(1<<0) : (1<<0); /* sticky highlight bpl[2] */ 278 | draw_rect(x+1, y+1, cap->w-1, cap->h-1, bpls, setclr); 279 | if ((key & 0x7f) == 0x44) /* Return needs a bodge.*/ 280 | draw_rect(x-7, y+1, 8, 14, bpls, setclr); 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /cracking/cracks/nzs/gnu_c/trainer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * trainer.c 3 | * 4 | * Example simple trainer intro in C. 5 | * 6 | * Written & released by Keir Fraser 7 | * 8 | * This is free and unencumbered software released into the public domain. 9 | * See the file COPYING for more details, or visit . 10 | */ 11 | 12 | static volatile struct m68k_vector_table * const m68k_vec = 13 | (struct m68k_vector_table *)0x0; 14 | static volatile struct amiga_custom * const cust = 15 | (struct amiga_custom *)0xdff000; 16 | static volatile struct amiga_cia * const ciaa = 17 | (struct amiga_cia *)0x0bfe001; 18 | /*static volatile struct amiga_cia * const ciab = 19 | (struct amiga_cia *)0x0bfdd00;*/ 20 | 21 | /* Space for bitplanes and unpacked font. */ 22 | extern char GRAPHICS[]; 23 | 24 | #define IRQ(name) \ 25 | static void c_##name(void) attribute_used; \ 26 | void name(void); \ 27 | asm ( \ 28 | #name": \n" \ 29 | " movem.l %d0-%d1/%a0-%a1,-(%sp) \n" \ 30 | " bsr c_"#name" \n" \ 31 | " movem.l (%sp)+,%d0-%d1/%a0-%a1 \n" \ 32 | " rte \n" \ 33 | ) 34 | 35 | #define xres 640 36 | #define yres 169 37 | #define bplsz (yres*xres/8) 38 | #define planes 2 39 | 40 | #define xstart 110 41 | #define ystart 20 42 | #define yperline 10 43 | 44 | static volatile uint8_t keycode_buffer; 45 | static uint8_t *bpl[2]; 46 | static uint16_t *font; 47 | 48 | static uint16_t copper[] = { 49 | 0x008e, 0x4681, /* diwstrt.v = 0x46 */ 50 | 0x0090, 0xefc1, /* diwstop.v = 0xef (169 lines) */ 51 | 0x0092, 0x003c, /* ddfstrt */ 52 | 0x0094, 0x00d4, /* ddfstop */ 53 | 0x0100, 0xa200, /* bplcon0 */ 54 | 0x0102, 0x0000, /* bplcon1 */ 55 | 0x0104, 0x0000, /* bplcon2 */ 56 | 0x0108, 0x0000, /* bpl1mod */ 57 | 0x010a, 0x0000, /* bpl2mod */ 58 | 0x00e0, 0x0000, /* bpl1pth */ 59 | 0x00e2, 0x0000, /* bpl1ptl */ 60 | 0x00e4, 0x0000, /* bpl2pth */ 61 | 0x00e6, 0x0000, /* bpl2ptl */ 62 | 0x0182, 0x0222, /* col01 */ 63 | 0x0184, 0x0ddd, /* col02 */ 64 | 0x0186, 0x0ddd, /* col03 */ 65 | 0x0180, 0x0103, /* col00 */ 66 | 0x4407, 0xfffe, 67 | 0x0180, 0x0ddd, 68 | 0x4507, 0xfffe, 69 | 0x0180, 0x0402, 70 | 0xf007, 0xfffe, 71 | 0x0180, 0x0ddd, 72 | 0xf107, 0xfffe, 73 | 0x0180, 0x0103, 74 | 0xffff, 0xfffe, 75 | }; 76 | 77 | struct char_row { 78 | uint8_t x, y; 79 | const char *s; 80 | }; 81 | 82 | static const struct char_row banner[] = { 83 | { 13, 0, "=====================" }, 84 | { 11, 1, "+ THE NEW ZEALAND STORY +" }, 85 | { 13, 2, "=====================" }, 86 | { 6, 3, "Cracked & Trained by KAF in June '11" }, 87 | { 0,10, "Space, Mouse button, or Joystick Fire to Continue!" }, 88 | { 0xff, 0xff, NULL } 89 | }; 90 | 91 | #define OPT_RANGE 1 92 | #define OPT_BOOL 2 93 | static struct option { 94 | uint8_t type:4; 95 | uint8_t dfl:4; 96 | uint8_t min:4; 97 | uint8_t max:4; 98 | const char *s; 99 | } opts[] = { 100 | { OPT_BOOL, .dfl = 0, .s = "Infinite Lives" }, 101 | { OPT_RANGE, .dfl = 3, .min = 1, .max = 10, .s = "Initial Lives" }, 102 | { OPT_BOOL, .dfl = 0, .s = "Load/Save Highscores" }, 103 | { OPT_BOOL, .dfl = 0, .s = "Reset Saved Highscores" }, 104 | { 0 } 105 | }; 106 | 107 | /* Wait for blitter idle. */ 108 | static void waitblit(void) 109 | { 110 | while (*(volatile uint8_t *)&cust->dmaconr & (1u << 6)) 111 | continue; 112 | } 113 | 114 | /* Wait for end of bitplane DMA. */ 115 | static void wait_bos(void) 116 | { 117 | while (*(volatile uint8_t *)&cust->vhposr != 0xf0) 118 | continue; 119 | } 120 | 121 | /* Wait for beam to move to next scanline. */ 122 | static void wait_line(void) 123 | { 124 | uint8_t v = *(volatile uint8_t *)&cust->vhposr; 125 | while (*(volatile uint8_t *)&cust->vhposr == v) 126 | continue; 127 | } 128 | 129 | static void clear_screen_rows(uint16_t y_start, uint16_t y_nr) 130 | { 131 | waitblit(); 132 | cust->bltcon0 = 0x0100; 133 | cust->bltcon1 = 0x0000; 134 | cust->bltdpt.p = bpl[0] + y_start * (xres/8); 135 | cust->bltdmod = 0; 136 | cust->bltsize = (xres/16)|(y_nr<<6); 137 | waitblit(); 138 | cust->bltdpt.p = bpl[1] + y_start * (xres/8); 139 | cust->bltsize = (xres/16)|(y_nr<<6); 140 | waitblit(); 141 | } 142 | 143 | static void clear_colors(void) 144 | { 145 | uint16_t i; 146 | for (i = 0; i < 16; i++) 147 | cust->color[i] = 0; 148 | } 149 | 150 | /* Unpack 8*8 font into destination. 151 | * Each char 00..7f is copied in sequence. 152 | * Destination is 10 longwords (= 10 rows) per character. 153 | * First word of each long is foreground, second word is background. 154 | * Background is computed from foreground. */ 155 | extern uint8_t packfont[]; 156 | static void unpack_font(void) 157 | { 158 | uint8_t *p = packfont; 159 | uint16_t i, j, x, *q = font; 160 | 161 | /* First 0x20 chars are blank. */ 162 | memset(q, 0, 0x20 * yperline * 4); 163 | q += 0x20 * yperline * 2; 164 | 165 | for (i = 0x20; i < 0x80; i++) { 166 | /* Foreground char is shifted right one pixel. */ 167 | q[0] = 0; 168 | for (j = 1; j < yperline-1; j++) 169 | q[2*j] = (uint16_t)(*p++) << 7; 170 | q[2*j] = 0; 171 | 172 | /* OR the neighbouring rows into each background pixel. */ 173 | q[1] = q[0] | q[2]; 174 | for (j = 1; j < yperline-1; j++) 175 | q[2*j+1] = q[2*(j-1)] | q[2*j] | q[2*(j+1)]; 176 | q[2*j+1] = q[2*(j-1)] | q[2*j]; 177 | 178 | /* OR the neighbouring columns into each background pixel. */ 179 | for (j = 0; j < yperline; j++) { 180 | x = q[2*j+1]; 181 | q[2*j+1] = (x << 1) | x | (x >> 1); 182 | } 183 | 184 | q += yperline * 2; 185 | } 186 | } 187 | 188 | static void print_char(uint16_t x, uint16_t y, char c) 189 | { 190 | uint16_t *font_char = font + c * yperline * 2; 191 | uint16_t i, bpl_off = y * (xres/8) + (x/16) * 2; 192 | 193 | waitblit(); 194 | 195 | cust->bltcon0 = 0x0dfc | ((x&15)<<12); /* ABD DMA, D = A|B, pre-shift A */ 196 | cust->bltcon1 = 0; 197 | cust->bltamod = 0; 198 | cust->bltbmod = xres/8 - 4; 199 | cust->bltdmod = xres/8 - 4; 200 | cust->bltafwm = 0xffff; 201 | cust->bltalwm = 0x0000; 202 | 203 | for (i = 0; i < 2; i++) { 204 | waitblit(); 205 | cust->bltapt.p = font_char + (i==0); 206 | cust->bltbpt.p = bpl[i] + bpl_off; 207 | cust->bltdpt.p = bpl[i] + bpl_off; 208 | cust->bltsize = 2 | (yperline<<6); /* 2 words * yperline rows */ 209 | } 210 | } 211 | 212 | static void print_line(const struct char_row *r) 213 | { 214 | uint16_t x = xstart + r->x * 8; 215 | uint16_t y = ystart + r->y * yperline; 216 | const char *p = r->s; 217 | char c; 218 | clear_screen_rows(y, yperline); 219 | while ((c = *p++) != '\0') { 220 | print_char(x, y, c); 221 | x += 8; 222 | } 223 | } 224 | 225 | static void print_screen(void) 226 | { 227 | const struct char_row *r; 228 | for (r = banner; r->x != 0xff; r++) 229 | print_line(r); 230 | } 231 | 232 | static void print_option(const struct option *opt, uint16_t nr) 233 | { 234 | char s[80], t[4] = "ON"; 235 | struct char_row r = { .x = 8, .y = 5 + nr, .s = s }; 236 | switch (opt->type) { 237 | case OPT_BOOL: 238 | sprintf(t, opt->dfl ? "ON" : "OFF"); 239 | break; 240 | case OPT_RANGE: 241 | sprintf(t, "%2u", opt->dfl); 242 | break; 243 | } 244 | sprintf(s, "F%u - %24s%s", (uint32_t)(nr+1), opt->s, t); 245 | print_line(&r); 246 | } 247 | 248 | static void setup_options(void) 249 | { 250 | const struct option *opt; 251 | uint16_t i; 252 | for (opt = opts, i = 0; opt->type; opt++, i++) 253 | print_option(opt, i); 254 | } 255 | 256 | static void update_option(uint8_t nr) 257 | { 258 | struct option *opt; 259 | if (nr > 3) 260 | return; 261 | opt = &opts[nr]; 262 | switch (opt->type) { 263 | case OPT_BOOL: 264 | opt->dfl = !opt->dfl; 265 | break; 266 | case OPT_RANGE: 267 | if (opt->dfl++ == opt->max) 268 | opt->dfl = opt->min; 269 | break; 270 | } 271 | print_option(opt, nr); 272 | } 273 | 274 | IRQ(CIAA_IRQ); 275 | static void c_CIAA_IRQ(void) 276 | { 277 | uint16_t i; 278 | uint8_t icr = ciaa->icr; 279 | 280 | if (icr & (1u<<3)) { /* SDR finished a byte? */ 281 | /* Grab and decode the keycode. */ 282 | uint8_t keycode = ~ciaa->sdr; 283 | keycode_buffer = (keycode >> 1) | (keycode << 7); /* ROR 1 */ 284 | /* Handshake over the serial line. */ 285 | ciaa->cra |= 1u<<6; /* start the handshake */ 286 | for (i = 0; i < 3; i++) /* wait ~100us */ 287 | wait_line(); 288 | ciaa->cra &= ~(1u<<6); /* finish the handshake */ 289 | } 290 | 291 | /* NB. Clear intreq.ciaa *after* reading/clearing ciaa.icr else we get a 292 | * spurious extra interrupt, since intreq.ciaa latches the level of CIAA 293 | * INT and hence would simply become set again immediately after we clear 294 | * it. For this same reason (latches level not edge) it is *not* racey to 295 | * clear intreq.ciaa second. Indeed AmigaOS does the same (checked 296 | * Kickstart 3.1). */ 297 | cust->intreq = 1u<<3; 298 | } 299 | 300 | uint32_t trainer(void) 301 | { 302 | uint32_t optres = 0; 303 | uint16_t i; 304 | uint8_t keycode; 305 | char *p; 306 | 307 | /* Set up CIAA ICR. We only care about keyboard. */ 308 | ciaa->icr = 0x7f; 309 | ciaa->icr = 0x88; 310 | 311 | /* Enable blitter DMA. */ 312 | cust->dmacon = 0x8040; 313 | 314 | /* Clear BSS. */ 315 | memset(_sbss, 0, _ebss-_sbss); 316 | 317 | /* Bitplanes and unpacked font allocated as directed by linker. */ 318 | p = GRAPHICS; 319 | bpl[0] = (uint8_t *)p; p += bplsz; 320 | bpl[1] = (uint8_t *)p; p += bplsz; 321 | font = (uint16_t *)p; 322 | 323 | /* Poke bitplane addresses into the copper. */ 324 | for (i = 0; copper[i] != 0x00e0/*bpl1pth*/; i++) 325 | continue; 326 | copper[i+1] = (uint32_t)bpl[0] >> 16; 327 | copper[i+3] = (uint32_t)bpl[0]; 328 | copper[i+5] = (uint32_t)bpl[1] >> 16; 329 | copper[i+7] = (uint32_t)bpl[1]; 330 | 331 | /* Clear bitplanes. */ 332 | clear_screen_rows(0, yres); 333 | 334 | clear_colors(); 335 | 336 | unpack_font(); 337 | 338 | m68k_vec->level2_autovector.p = CIAA_IRQ; 339 | cust->cop1lc.p = copper; 340 | 341 | print_screen(); 342 | setup_options(); 343 | 344 | wait_bos(); 345 | cust->dmacon = 0x81c0; /* enable copper/bitplane/blitter DMA */ 346 | cust->intena = 0x8008; /* enable CIA-A interrupts */ 347 | 348 | /* Loop while no LMB or joystick fire. */ 349 | while ((ciaa->pra & 0xc0) == 0xc0) { 350 | wait_bos(); 351 | if ((keycode = keycode_buffer)) { 352 | keycode_buffer = 0; 353 | /* Space? Break. */ 354 | if (keycode == 0x40) 355 | break; 356 | update_option(keycode - 0x50); 357 | } 358 | } 359 | 360 | /* Wait for idle then knock it on the head. */ 361 | waitblit(); 362 | wait_bos(); 363 | cust->dmacon = 0x01c0; 364 | cust->intena = 0x0008; 365 | clear_colors(); 366 | 367 | /* Marshal selected options into a packed longword. */ 368 | for (i = 0; i < 4; i++) { 369 | optres <<= 4; 370 | optres |= opts[i].dfl; 371 | } 372 | 373 | return optres; 374 | } 375 | 376 | asm ( 377 | " .data \n" 378 | "packfont: .incbin \"../FONT2_8X8.BIN\"\n" 379 | " .text \n" 380 | ); 381 | --------------------------------------------------------------------------------