From: Toni Wilen Date: Thu, 30 May 2019 19:09:11 +0000 (+0300) Subject: ussload moved to separate repository X-Git-Tag: 4300~196 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=640e938169c939cda70b2ea25d061638248ae94e;p=francis%2Fwinuae.git ussload moved to separate repository --- diff --git a/utilities/stateload/asm.S b/utilities/stateload/asm.S deleted file mode 100644 index 27088504..00000000 --- a/utilities/stateload/asm.S +++ /dev/null @@ -1,301 +0,0 @@ - -CPU_CHUNK = 4 -CIAA_CHUNK = CPU_CHUNK+4 -CIAB_CHUNK = CIAA_CHUNK+4 -CUSTOM_CHUNK = CIAB_CHUNK+4 -AGA_COLORS_CHUNK = CUSTOM_CHUNK+4 -FLOPPY_CHUNK = AGA_COLORS_CHUNK+4 -AUDIO_CHUNK = FLOPPY_CHUNK+4*4 -SPRITE_CHUNK = AUDIO_CHUNK+4*4 -MMU_TABLE = SPRITE_CHUNK+4*8 - - .text - .globl _runit - .globl _killsystem - .globl _callinflate - .globl _inflate - .globl _flushcache - -_flushcache: - move.l a6,-(sp) - move.l 4.w,a6 - jsr -0x27c(a6) | CacheClearU - move.l (sp)+,a6 - rts - -_callinflate: - movem.l a4-a5,-(sp) - move.l 4+2*4(sp),a4 - move.l 8+2*4(sp),a5 - bsr _inflate - movem.l (sp)+,a4-a5 - rts - - | params: new stack 4, uaestate 8, func(uaestate) 12 -_killsystem: - move.l 8(sp),a0 | uaestate - move.l a6,a1 - move.l 4.w,a6 - move.w 0x128(a6),(a0) | AttFlags - move.l sp,d1 - move.l a0,d0 - move.l a5,a0 - lea .super(pc),a5 - jsr -0x1e(a6) | Supervisor -.super: - move.w #0x2700,sr - move.l a0,a5 - move.l a1,a6 - move.l d0,a0 - - | debug trigger - move.w #0x1234,0xef0006 - - | check if 68060 - move.l 0x10.w,a1 - btst #2,1(a0) - beq.s .not68060 - moveq #0,d0 - movec d0,VBR - pea .not68060(pc) - move.l (sp)+,0x10.w - | movec PCR,d0 - dc.w 0x4e7a,0x0808 - | it is 68060 - bset #7,1(a0) -.not68060: - move.l a1,0x10.w - - | CIA: stop timers, clear interrupts - bclr #0,0xbfde00 - bclr #0,0xbfdf00 - bclr #0,0xbfee01 - bclr #0,0xbfef01 - move.b #0x7f,0xbfdd00 - move.b #0x7f,0xbfed01 - tst.b 0xbfdd00 - tst.b 0xbfed01 - - lea 0xdff000,a0 - move.w #0x7fff,d0 - move.w d0,0x96(a0) - move.w d0,0x9a(a0) - move.w d0,0x9c(a0) - move.w d0,0x9e(a0) - move.l d1,a0 - - move.l 8(a0),d0 - bsr.w mmu_enable - - move.l 4(a0),sp | new temp super stack - move.l 8(a0),-(sp) | uaestate - move.l 12(a0),a0 | func - jsr (a0) | func(uaestate) - | never returns - -_runit: - move.l 4(sp),a4 | get pointer to struct uaestate - subq.l #8,sp - lea 0xdff000,a6 - -| find last line - moveq #0,d5 - lea 0x6(a6),a2 -.wait1: - cmp.b #250,(a2) - bne.s .wait1 -.wait1a: - cmp.b #2,(a2) - bne.s .wait1a -.wait1b: - move.w 4(a6),d0 - btst #0,d0 - beq.s .wait1c - move.b (a2),d0 - cmp.b d0,d5 - bcc.s .wait1b - move.b d0,d5 - bra.s .wait1b -.wait1c: - cmp.b #160,(a2) - bne.s .wait1c - - | last line - 15 - sub.b #15,d5 -.wait3: - cmp.b (a2),d5 - bne.s .wait3 - - | debug trigger - move.w #0x1234,0xef0004 - - move.l CUSTOM_CHUNK(a4),a0 - move.w 4+0x96(a0),d0 | DMACON - and.w #15,d0 - or.w #0x8200,d0 - | enable audio DMA - move.w d0,0x96(a6) - - | wait few lines, enough time for audio channels to enter normal 2/3 states - addq.b #4,d5 -.wait4: - cmp.b (a2),d5 - bne.s .wait4 - | restore latched AUDxLEN and AUDxPT - move.l a4,(sp) - bsr _set_audio_final - - | restore possible side-effect causing - | custom bits as late as possible - - move.l CIAA_CHUNK(a4),(sp) - clr.l 4(sp) - bsr _set_cia_final - move.l CIAB_CHUNK(a4),(sp) - addq.l #1,4(sp) - bsr _set_cia_final - move.l CUSTOM_CHUNK(a4),(sp) - bsr _set_custom_final - - | restore CPU state - move.w (a4),d1 - move.l CPU_CHUNK(a4),a0 - move.l 4+4+60+4+2+2+4(a0),SP - move.l 4+4+60+4+2+2(a0),a1 | USP - move.l a1,USP - cmp.l #68020,(a0) - bcs.s .cpu68010 - btst #1,d1 - beq.s .cpu68010 - lea 4+4+60+4+2+2+4+4+2+4+4+4+4(a0),a1 - | CAAR is 68020/030 only - move.l (a1)+,d0 - btst #3,d1 - bne.s .cpu68040 - | movec d0,CAAR - dc.w 0x4e7b,0x0802 -.cpu68040: - move.l (a1)+,d0 - movec d0,CACR - | MSP is 68020-68040 only - move.l (a1)+,d0 - btst #7,d1 - bne.s .cpu68010 - movec d0,MSP -.cpu68010: - cmp.l #68010,(a0) - bcs.s .cpu68000 - btst #0,d1 - beq.s .cpu68000 - lea 4+4+60+4+2+2+4+4+2+4(a0),a1 - move.l (a1)+,d0 - movec d0,DFC - move.l (a1)+,d0 - movec d0,SFC - move.l (a1)+,d0 - movec d0,VBR -.cpu68000: - btst #0,d1 - beq.s .nocpu68010 - btst #1,d1 - beq.s .nocpu68020 - btst #0,3(a4) | nocache? - beq.s .nocpu68020 - moveq #0,d0 - movec d0,CACR -.nocpu68020: - move.w #0x0020,-(sp) | Format 0, Trap #0 -.nocpu68010: - - move.l CIAA_CHUNK(a4),a1 - move.b 15(a1),d6 - swap d6 - move.b 14(a1),d6 - move.l CIAB_CHUNK(a4),a1 - move.b 15(a1),d7 - swap d7 - move.b 14(a1),d7 - - move.l 4+4+60(a0),-(sp) | PC - move.w 4+4+60+4+2+2+4+4(a0),-(sp) | SR - movem.l 4+4(a0),d0-d5 - movem.l 4+4+8*4+4+4(a0),a2-a6 - add.w #4+4+6*4,a0 - - | debug trigger - move.w #0x1234,0xef0000 - - lea 0xbfde00,a1 - - | wait last line -.wait2: - tst.b 0xdff006 - bne.s .wait2 - - | start timers - move.b d6,0xbfee01-0xbfde00(a1) - swap d6 - move.b d6,0xbfef01-0xbfde00(a1) - move.b d7,(a1) - swap d7 - move.b d7,0x100(a1) - - movem.l (a0),d6-d7/a0-a1 - - rte | GO! GO! GO! - -mmu_enable: - movem.l d0-d2/a0-a2,-(sp) - move.l d0,a2 - - | debug trigger - move.w #0x1234,0xef0008 - - move.l MMU_TABLE(a2),d2 - beq.s .mmuend - - move.w (a2),d1 - btst #3,d1 - beq.s .no68040 - - | 68040/060 - movec d2,urp - movec d2,srp - cpusha dc - cinva dc - pflusha - move.l #0x8000,d0 - movec d0,tc - moveq #0,d0 - movec d0,itt0 - movec d0,itt1 - movec d0,dtt0 - movec d0,dtt1 - bra.s .mmuend - -.no68040: - | 68030? - btst #2,d1 - beq.s .mmuend - - sub.w #12,sp - move.l #0x00c07760,(sp) - | pmove (sp),tc - dc.w 0xf017,0x4000 - move.l #0x80000002,4(sp) - move.l d2,8(sp) - | pmove 4(sp),crp - dc.w 0xf02f,0x4c00,0x0004 - bset #7,(sp) - | pmove (sp),tc - dc.w 0xf017,0x4000 - clr.l (sp) - | pmove (sp),tt0 - dc.w 0xf017,0x0800 - | pmove (sp),tt1 - dc.w 0xf017,0x0c00 - add.w #12,sp - -.mmuend: - movem.l (sp)+,d0-d2/a0-a2 - rts diff --git a/utilities/stateload/header.h b/utilities/stateload/header.h deleted file mode 100644 index 5810b0d2..00000000 --- a/utilities/stateload/header.h +++ /dev/null @@ -1,100 +0,0 @@ - -#define TEMP_STACK_SIZE 8000 - -#define ALLOCATIONS 256 - -struct Allocation -{ - struct MemHeader *mh; - UBYTE *addr; - ULONG size; -}; - -struct MemoryBank -{ - UBYTE *addr; - ULONG flags; - UBYTE *targetaddr; - ULONG size; - ULONG targetsize; - ULONG offset; - UBYTE chunk[5]; -}; - -// CHIP, SLOW, FAST -#define MEMORY_REGIONS 3 -#define MB_CHIP 0 -#define MB_SLOW 1 -#define MB_FAST 2 - -#define MAPROM_ACA500 1 -#define MAPROM_ACA500P 2 -#define MAPROM_ACA1221EC 3 -#define MAPROM_ACA12xx 4 -#define MAPROM_GVP 5 -#define MAPROM_BLIZZARD12x0 6 -#define MAPROM_ACA1233N 7 -#define MAPROM_MMU 255 - -#define FLAGS_NOCACHE 1 -#define FLAGS_FORCEPAL 2 -#define FLAGS_FORCENTSC 4 - -struct mapromdata -{ - UWORD type; - ULONG config; - ULONG addr; - APTR board; - ULONG memunavailable; -}; - -struct uaestate -{ - ULONG flags; - UBYTE *cpu_chunk; - UBYTE *ciaa_chunk, *ciab_chunk; - UBYTE *custom_chunk; - UBYTE *aga_colors_chunk; - UBYTE *floppy_chunk[4]; - UBYTE *audio_chunk[4]; - UBYTE *sprite_chunk[8]; - ULONG *MMU_Level_A; - - UBYTE *maprom; - ULONG mapromsize; - ULONG maprom_memlimit; - struct mapromdata mrd[2]; - - UBYTE *extra_ram; - ULONG extra_ram_size; - ULONG errors; - - struct MemHeader *mem_allocated[MEMORY_REGIONS]; - struct MemHeader *extra_mem_head; - UBYTE *extra_mem_pointer; - struct MemoryBank membanks[MEMORY_REGIONS]; - - int num_allocations; - struct Allocation allocations[ALLOCATIONS]; - - WORD mmutype; - UBYTE *page_ptr; - ULONG page_free; - - UWORD romver, romrev; - UBYTE agastate; - UBYTE usemaprom; - UBYTE debug; - UBYTE testmode; - UBYTE nowait; - UBYTE canusemmu; - UBYTE mmuused; -}; - -UBYTE *allocate_abs(ULONG size, ULONG addr, struct uaestate *st); - -BOOL map_region(struct uaestate *st, void *addr, void *physaddr, ULONG size, BOOL invalid, BOOL writeprotect, BOOL supervisor, UBYTE cachemode); -BOOL unmap_region(struct uaestate *st, void *addr, ULONG size); -BOOL init_mmu(struct uaestate *st); - diff --git a/utilities/stateload/inflate.S b/utilities/stateload/inflate.S deleted file mode 100644 index bdd5a099..00000000 --- a/utilities/stateload/inflate.S +++ /dev/null @@ -1,778 +0,0 @@ - - .chip 68020 - .globl _inflate - - -/* - * inflate.S - * - * Decompression of DEFLATE streams, as produced by zip/gzip/pkzip and - * specified in RFC 1951 "DEFLATE Compressed Data Format Specification". - * - * Usage: Optionally configure the OPT_xxx options below at build time; - * at run time 'bsr inflate' with arguments: - * a4 = output buffer, a5 = input stream - * a6 = *end* of temporary storage area (only if OPT_STORAGE_OFFSTACK) - * All register values (including arguments) are preserved. - * - * Space requirements: 638-930 bytes code; 2044-2940 bytes stack. - * (NB1. Above ranges are [No Optimisations]-[All Optimisations]) - * (NB2. Stack space can be relocated to a separately-specified storage - * area, see OPT_STORAGE_OFFSTACK below) - * - * Timings: With all Optimisation Options enabled (see below) this routine - * will decompress on a basic 7MHz 68000 at ~25kB/s. An AmigaDOS track of - * data (5.5kB) is processed in ~220ms. This is only fractionally slower than - * the track can be fetched from disk, hence there is scope for a - * decompressing loader to keep CPU and disk both at near 100% utilisation. - * - * Written & released by Keir Fraser - * - * This is free and unencumbered software released into the public domain. - * See the file COPYING for more details, or visit . - */ - -/* Optimisation Option #1: - * Avoid long Huffman-tree walks by indexing the first 8 bits of each codeword - * in a 256-entry lookup table. This shortens all walks by 8 steps and since - * the most common codes are less than 8 bits, most tree walks are avoided. - * Also pre-shifts selected symbols in the code->symbol table, ready to be used - * as indexes into further lookup tables. - * SPEEDUP: 41% (c.w. no Options); COST: 122 bytes code, 896 bytes stack */ -#ifndef OPT_TABLE_LOOKUP -#define OPT_TABLE_LOOKUP 1 -#endif - -/* Optimisation Option #2: - * Inline functions in the main decode loop to avoid all BSR/RTS pairs. - * SPEEDUP: 15% (on top of Option #1); COST: 164 bytes code */ -#ifndef OPT_INLINE_FUNCTIONS -#define OPT_INLINE_FUNCTIONS 1 -#endif - -/* Optimisation Option #3: - * Unroll the copy loop for tuples by one iteration - * (so two bytes are copied per iteration). - * SPEEDUP: ~1% (on top of Options #1 and #2); COST: 6 bytes code */ -#ifndef OPT_UNROLL_COPY_LOOP -#define OPT_UNROLL_COPY_LOOP 1 -#endif - -/* Storage Option: - * All but 12 bytes of this routine's space requirement can be allocated - * off stack, in a data area specified in register a6. - * If this option is set then inflate must be called with a6 pointing at - * the *end* of the reserved storage area (+2032 or +2928 bytes, depending - * on whether OPT_TABLE_LOOKUP is enabled). - * SPEEDUP: none; COST: -2 bytes code (makes code slightly smaller) */ -#ifndef OPT_STORAGE_OFFSTACK -#define OPT_STORAGE_OFFSTACK 0 -#endif - -/* By default all lookup/conversion tables are generated on-the-fly on every - * call to inflate. In some cases this can be very inefficient. - * If this option is enabled then two new routines are generated: At start-of- - * day call 'inflate_gentables' with a6 pointing to the *end* of a 6000-byte - * block of memory. Then call 'inflate_fromtables' instead of 'inflate', with - * a6 still pointing to the end of the pre-generated memory block. - * SPEEDUP: variable; COST: 116 bytes code */ -#ifndef OPT_PREGENERATE_TABLES -#define OPT_PREGENERATE_TABLES 0 -#endif - -/* By default all registers are saved/restored across 'inflate' and - * 'inflate_fromtables'. This set can be reduced below. Note that if - * a4 is not saved then it will point at the end of the uncompressed output. - * If a5 is not saved then it will point at the end of the DEFLATE stream. */ -#ifndef SAVE_RESTORE_REGS -#define SAVE_RESTORE_REGS d0-d6/a0-a3 -#endif - -#if OPT_STORAGE_OFFSTACK -#define aS a6 -#else -#define aS sp -#endif - -/* Longest possible code. */ -#define MAX_CODE_LEN 16 - -/* (Maximum) alphabet sizes. */ -#define nr_codelen_symbols 19 -#define nr_litlen_symbols 288 -#define nr_distance_symbols 32 - -/* Alphabet-description stream for a static Huffman block (BTYPE=01b). */ -static_huffman_prefix: - dc.b 0xff, 0x5b, 0x00, 0x6c, 0x03, 0x36, 0xdb - dc.b 0xb6, 0x6d, 0xdb, 0xb6, 0x6d, 0xdb, 0xb6 - dc.b 0xcd, 0xdb, 0xb6, 0x6d, 0xdb, 0xb6, 0x6d - dc.b 0xdb, 0xa8, 0x6d, 0xce, 0x8b, 0x6d, 0x3b - -#if OPT_TABLE_LOOKUP - -/* Number of bytes required for code-lookup table/tree: - * - 256 2-byte entries for the 8-bit lookup table - * - Worst-case only 8 symbols decode directly in the table and all the rest - * are in a tree hanging off one table entry. This tree requires - * (nr_symbols-8)-1 internal 4-byte nodes. */ -#define LOOKUP_BYTES(nr_syms) (256*2+((nr_syms)-9)*4) - - /* a0 = len[], a1 = nodes[], d0 = nr_symbols */ - /* d1 = symbol beyond which all symbols get <<2 */ - /* a2-a3 are scratched */ -build_code: - movem.l d0-d7,-(aS) - - /* Allocate space for bl_count[]/next_code[] array on stack. */ - moveq #(MAX_CODE_LEN+1)/2,d1 - moveq #0,d2 -1: move.l d2,-(aS) - dbf d1,1b - - /* Count occurrences of each code length into bl_count[] array. */ - subq.w #1,d0 - move.w d0,d1 - move.l a0,a2 /* a2 = &len[0] */ -1: move.b (a2)+,d2 /* d2 = len[i] */ -#if MC68020 - addq.w #1,(aS,d2.w*2) -#else - add.b d2,d2 - addq.w #1,(aS,d2.w) /* bl_count[len[i]]++ */ -#endif - dbf d1,1b - - /* Calculate next_code[] start values for each code length. */ - move.l aS,a2 /* a2 = bl_count[] / next_code[] */ - moveq #MAX_CODE_LEN-1,d1 - moveq #0,d2 /* d2 = code */ - move.w d2,(aS) /* bl_count[0] = 0, ignore zero-length codes */ -1: add.w (a2),d2 - add.w d2,d2 /* code = (code + bl_count[i-1]) << 1 */ - move.w d2,(a2)+ /* next_code[i] = code */ - dbf d1,1b - - /* Create the Huffman-code lookup tree */ - move.w d0,d1 - moveq #127,d4 /* d4 = next_node = 127 */ - move.l a0,a2 /* a2 = &len[0] */ -1: moveq #0,d5 - move.b (a2)+,d5 /* d5 = len[i] / *len++ */ - jeq 4f - subq.w #1,d5 - move.w d5,d6 -#if MC68020 - move.w (aS,d6.w*2),d3 - addq.w #1,(aS,d6.w*2) -#else - add.w d6,d6 - move.w (aS,d6.w),d3 /* d3 = code = next_code[len[i]]++ */ - addq.w #1,(aS,d6.w) - move.w d5,d6 -#endif - - moveq #0,d2 -9: lsr.w #1,d3 - roxl.w #1,d2 - dbf d6,9b /* d5 = codelen-1; d2 = reversed code */ - move.b d2,d3 - add.w d3,d3 /* d3 = table offset */ - move.w d0,d6 - sub.w d1,d6 /* d6 = symbol */ - cmp.w (((MAX_CODE_LEN+1)/2)+1)*4+6(aS),d6 /* symbol > saved d1.w? */ - jls 9f - lsl.w #2,d6 /* symbol <<= 2 if so */ -9: cmp.b #9-1,d5 - jcc codelen_gt_8 - -codelen_le_8: /* codelen <= 8: leaf in table entry(s) */ - lsl.w #3,d6 - or.b d5,d6 /* d6 = (symbol<<3) | (codelen-1) */ - moveq #0,d2 - addq.b #2,d5 - bset d5,d2 /* d2 = 1<<(codelen+1) [table step] */ - move.w d2,d7 - neg.w d7 - and.w #511,d7 - or.w d7,d3 /* d3 = last table offset */ -9: move.w d6,(a1,d3.w) - sub.w d2,d3 - jcc 9b - jra 4f - -codelen_gt_8: /* codelen > 8: requires a tree walk */ - lsr.w #8,d2 - subq.b #8,d5 /* Skip the first 8 bits of code */ - lea (a1,d3.w),a3 /* pnode = table entry */ - -2: /* Walk through *pnode. */ - move.w (a3),d7 /* d3 = *pnode */ - jne 3f - /* Link missing: Create a new internal node */ - addq.w #1,d4 - move.w d4,d7 - bset #15,d7 - move.w d7,(a3) /* *pnode = ++next_node | INTERNAL */ -3: /* Take left or right branch depending on next code bit */ - lsr.b #1,d2 - addx.w d7,d7 -#if MC68020 - lea (a1,d7.w*2),a3 -#else - add.w d7,d7 - lea (a1,d7.w),a3 /* pnode = next_bit ? &node->r : &node->l */ -#endif -3: dbf d5,2b - - /* Insert the current symbol as a new leaf node */ - move.w d6,(a3) /* *pnode = sym */ -4: dbf d1,1b - - lea (((MAX_CODE_LEN+1)/2)+1)*4(aS),aS - movem.l (aS)+,d0-d7 - rts - - /* d5-d6/a5 = stream, a0 = tree */ - /* d0.w = result, d1.l = scratch */ -.macro STREAM_NEXT_SYMBOL - moveq #0,d0 /* 4 */ - moveq #7,d1 /* 4 */ - cmp.b d1,d6 /* 4 */ - jhi 99f /* 10 */ - /* Less than 8 bits cached; grab another byte from the stream */ - move.b (a5)+,d0 /* [8] */ - lsl.w d6,d0 /* [~14] */ - or.w d0,d5 /* [4] */ /* s->cur |= *p++ << s->nr */ - addq.b #8,d6 /* [4] */ /* s->nr += 8 */ - moveq #0,d0 /* [4] */ -99: /* Use next input byte as index into code lookup table */ - move.b d5,d0 /* 4 */ -#if MC68020 - move.w (a0,d0.w*2),d0 -#else - add.w d0,d0 /* 4 */ - move.w (a0,d0.w),d0 /* 14 */ -#endif - jpl 99f /* 10 (taken) */ - /* Code is longer than 8 bits: do the remainder via a tree walk */ - lsr.w #8,d5 - subq.b #8,d6 /* consume 8 bits from the stream */ -98: /* stream_next_bits(1), inlined & optimised */ - subq.b #1,d6 /* 4 cy */ - jcc 97f /* 10 cy (taken) */ - move.b (a5)+,d5 /* [8 cy] */ - moveq #7,d6 /* [4 cy] */ -97: lsr.w #1,d5 /* 8 cy */ - addx.w d0,d0 /* 4 cy */ -#if MC68020 - move.w (a0,d0.w*2),d0 -#else - add.w d0,d0 /* 4 cy */ - move.w (a0,d0.w),d0 /* 14 cy */ -#endif - jmi 98b /* 10 cy (taken); loop on INTERNAL flag */ - jra 98f /* TOTAL LOOP CYCLES ~= 54 */ -99: /* Symbol found directly: consume bits and return symbol */ - and.b d0,d1 /* 4 */ - addq.b #1,d1 /* 4 */ - lsr.w d1,d5 /* ~16 */ /* consume bits from the stream */ - sub.b d1,d6 /* 4 */ - lsr.w #3,d0 /* 12 */ /* d0 = symbol */ -98: /* ~94 CYCLES TOTAL [+ 34] */ -.endm - -#else /* !OPT_TABLE_LOOKUP */ - -/* Number of bytes required for code-lookup tree: - * - Every binary tree with N leaves has N-1 internal nodes. - * - Internal nodes require 4 bytes each. Leaves are free. */ -#define LOOKUP_BYTES(nr_syms) (((nr_syms)-1)*4) - - /* a0 = len[], a1 = nodes[], d0 = nr_symbols */ - /* a2-a3 are scratched */ -build_code: - movem.l d0-d5,-(aS) - - /* Allocate space for bl_count[]/next_code[] array on stack. */ - moveq #(MAX_CODE_LEN+1)/2,d1 - moveq #0,d2 -1: move.l d2,-(aS) - dbf d1,1b - - /* Count occurrences of each code length into bl_count[] array. */ - subq.w #1,d0 - move.w d0,d1 - move.l a0,a2 /* a2 = &len[0] */ -1: move.b (a2)+,d2 /* d2 = len[i] */ - add.b d2,d2 - addq.w #1,(aS,d2.w) /* bl_count[len[i]]++ */ - dbf d1,1b - - /* Calculate next_code[] start values for each code length. */ - move.l aS,a2 /* a2 = bl_count[] / next_code[] */ - moveq #MAX_CODE_LEN-1,d1 - moveq #0,d2 /* d2 = code */ - move.w d2,(aS) /* bl_count[0] = 0, ignore zero-length codes */ -1: add.w (a2),d2 - add.w d2,d2 /* code = (code + bl_count[i-1]) << 1 */ - move.w d2,(a2)+ /* next_code[i] = code */ - dbf d1,1b - - /* Create the Huffman-code lookup tree */ - move.w d0,d1 - moveq #0,d4 /* d4 = next_node */ - move.l a0,a2 /* a2 = &len[0] */ -1: moveq #0,d5 - move.b (a2)+,d5 /* d5 = len[i] / *len++ */ - jeq 4f - subq.w #1,d5 - add.w d5,d5 - move.w (aS,d5.w),d3 /* d3 = code = next_code[len[i]]++ */ - addq.w #1,(aS,d5.w) - lsr.w #1,d5 - /* Walk down the tree, creating nodes as necessary */ - moveq #0,d2 /* d2 = 0 (root node) */ - jra 3f - -2: /* Walk through *pnode. */ - move.w (a3),d2 /* d2 = *pnode */ - jne 3f - /* Link missing: Create a new internal node */ - addq.w #1,d4 - move.w d4,d2 - bset #15,d2 - move.w d2,(a3) /* *pnode = ++next_node | INTERNAL */ -3: /* Take left or right branch depending on next code bit */ - lsl.w #2,d2 - btst d5,d3 - jeq 3f - addq.w #2,d2 -3: lea (a1,d2.w),a3 /* pnode = next_bit ? &node->r : &node->l */ - dbf d5,2b - - /* Insert the current symbol as a new leaf node */ - move.w d0,d2 - sub.w d1,d2 - move.w d2,(a3) /* *pnode = sym */ -4: dbf d1,1b - - lea (((MAX_CODE_LEN+1)/2)+1)*4(aS),aS - movem.l (aS)+,d0-d5 - rts - - /* d5-d6/a5 = stream, a0 = tree */ - /* d0.w = result */ -.macro STREAM_NEXT_SYMBOL - moveq #0,d0 -99: /* stream_next_bits(1), inlined & optimised */ - subq.b #1,d6 /* 4 cy */ - jcc 98f /* 10 cy (taken) */ - move.b (a5)+,d5 /* [8 cy] */ - moveq #7,d6 /* [4 cy] */ -98: lsr.w #1,d5 /* 8 cy */ - addx.w d0,d0 /* 4 cy */ - add.w d0,d0 /* 4 cy */ - move.w (a0,d0.w),d0 /* 14 cy */ - jmi 99b /* 10 cy (taken); loop on INTERNAL flag set */ - /* TOTAL LOOP CYCLES ~= 54 */ -.endm - -#endif - - /* d1.b = nr, d5-d6/a5 = stream [fetched_bits/nr_fetched_bits/inp] */ - /* d0.w = result */ -.macro STREAM_NEXT_BITS -99: moveq #0,d0 - cmp.b d1,d6 - jcc 99f /* while (s->nr < nr) */ - move.b (a5)+,d0 - lsl.l d6,d0 - or.l d0,d5 /* s->cur |= *p++ << s->nr */ - addq.b #8,d6 /* s->nr += 8 */ - jra 99b -99: bset d1,d0 - subq.w #1,d0 /* d0 = (1<cur & ((1<cur >>= nr */ - sub.b d1,d6 /* s->nr -= nr */ -.endm - -#if OPT_INLINE_FUNCTIONS -#define INLINE_stream_next_bits STREAM_NEXT_BITS -#define INLINE_stream_next_symbol STREAM_NEXT_SYMBOL -#else -#define INLINE_stream_next_bits jbsr stream_next_bits -#define INLINE_stream_next_symbol jbsr stream_next_symbol -#endif - -stream_next_bits: - STREAM_NEXT_BITS - rts - - /* d5-d6/a5 = stream, a4 = output */ - /* d0-d1 are scratched */ -uncompressed_block: -#if OPT_TABLE_LOOKUP - /* Push whole bytes back into input stream. */ - lsr.w #3,d6 - sub.w d6,a5 -#else - /* No need to push bytes back into input stream because stream_next_ - * {bits,symbol} will never leave more than 7 bits cached. */ -#endif - /* Snap input stream up to byte boundary. */ - moveq #0,d5 - moveq #0,d6 - /* Read block header and copy LEN bytes. */ - moveq #16,d1 - jbsr stream_next_bits /* LEN */ - addq.w #2,a5 /* skip NLEN */ - subq.w #1,d0 /* d0.w = len-1 (for dbf) */ -1: move.b (a5)+,(a4)+ - dbf d0,1b - rts - -#define o_hdist /*0*/ -#define o_hlit 2 -#define o_lens (o_hlit+2) -#define o_codelen_tree (o_lens+nr_litlen_symbols+nr_distance_symbols) -#if OPT_TABLE_LOOKUP -/* Lit/len and codelen lookup structures share space. */ -#define o_litlen_tree o_codelen_tree -#else -#define o_litlen_tree (o_codelen_tree+LOOKUP_BYTES(nr_codelen_symbols)) -#endif -#define o_dist_tree (o_litlen_tree+LOOKUP_BYTES(nr_litlen_symbols)) -#define o_stream (o_dist_tree+LOOKUP_BYTES(nr_distance_symbols)) -#define o_frame (o_stream+3*4) -#if OPT_STORAGE_OFFSTACK -#define o_mode (o_frame) -#else -/* Allow for BSR return address from decoder */ -#define o_mode (o_frame+4) -#endif -#define o_dist_extra (o_mode+4) -#define o_length_extra (o_dist_extra+30*4) - - /* d5-d6/a5 = stream, a4 = output */ - /* d0-d4,a0-a3 are scratched */ -static_huffman: - movem.l d5-d6/a5,-(aS) - moveq #0,d5 - moveq #0,d6 - lea static_huffman_prefix(pc),a5 - move.w #o_stream/4-2,d0 - jra 1f - - /* d5-d6/a5 = stream, a4 = output */ - /* d0-d4,a0-a3 are scratched */ -dynamic_huffman: - /* Allocate stack space for len[] and node[] arrays */ - move.w #o_frame/4-2,d0 -1: moveq #0,d1 -1: move.l d1,-(aS) - dbf d0,1b - /* HLIT = stream_next_bits(5) + 257 */ - moveq #5,d1 - jbsr stream_next_bits - add.w #257,d0 - move.w d0,-(aS) - /* HDIST = stream_next_bits(5) + 1 */ - moveq #5,d1 - jbsr stream_next_bits - addq.w #1,d0 - move.w d0,-(aS) - /* HCLEN = stream_next_bits(4) + 4 */ - moveq #4,d1 - jbsr stream_next_bits - addq.w #4-1,d0 /* -1 for dbf */ - /* Initialise len[] array with code-length symbol code lengths */ - lea codelen_order(pc),a1 - lea o_lens(aS),a0 /* a0 = len[] */ - moveq #0,d2 - move.w d0,d3 -1: moveq #3,d1 - jbsr stream_next_bits - move.b (a1)+,d2 - move.b d0,(a0,d2.w) /* len[codelen_order[i++]] = next_bits(3) */ - dbf d3,1b - /* Build the codelen_tree */ - lea o_codelen_tree(aS),a1 - moveq #nr_codelen_symbols,d0 -#if OPT_TABLE_LOOKUP - moveq #127,d1 /* don't left-shift any symbols */ -#endif - jbsr build_code /* build_code(codelen_tree) */ - /* Read the literal/length & distance code lengths */ - move.w o_hlit(aS),d2 - add.w o_hdist(aS),d2 - subq.w #1,d2 /* d2 = hlit+hdist-1 */ - move.l a0,a2 /* a2 = len[] */ - move.l a1,a0 /* a0 = a1 = codelen_tree */ -1: INLINE_stream_next_symbol - cmp.b #16,d0 - jcs c_lit - jeq c_16 - cmp.b #17,d0 - jeq c_17 -c_18: /* 18: Repeat zero N times */ - moveq #7,d1 - jbsr stream_next_bits - addq.w #11-3,d0 - jra 2f -c_17: /* 17: repeat zero N times */ - moveq #3,d1 - jbsr stream_next_bits -2: moveq #0,d1 - jra 3f -c_16: /* 16: repeat previous N times */ - moveq #2,d1 - jbsr stream_next_bits - move.b -1(a2),d1 -3: addq.w #3-1,d0 - sub.w d0,d2 -4: move.b d1,(a2)+ - dbf d0,4b - jra 5f -c_lit: /* 0-16: Literal symbol */ - move.b d0,(a2)+ -5: dbf d2,1b - /* Build the lit/len and distance trees */ -#if OPT_TABLE_LOOKUP - /* Clear the codelen tree (shared space with lit/len tree). - * NB. a0 = a1 = codelen_tree = litlen_tree */ - moveq #0,d0 - move.w #LOOKUP_BYTES(nr_codelen_symbols)/4-1,d1 -1: move.l d0,(a0)+ - dbf d1,1b - /* litlen_tree (= codelen_tree) is already in a1, and now zeroed. */ -#else - lea o_litlen_tree(aS),a1 -#endif - lea o_lens(aS),a0 - move.w o_hlit(aS),d0 -#if OPT_TABLE_LOOKUP - move.w #256,d1 - move.w d1,d4 /* left-shift symbols >127 (i.e., lengths) */ -#endif - jbsr build_code /* build_code(litlen_tree) */ - add.w d0,a0 - lea o_dist_tree(aS),a1 - move.w o_hdist(aS),d0 -#if OPT_TABLE_LOOKUP - moveq #0,d1 /* left-shift all symbols (i.e., distances) */ -#endif - jbsr build_code /* build_code(dist_tree) */ - /* Reinstate the main stream if we used the static prefix */ - tst.l o_stream+8(aS) - jeq decode_loop - movem.l o_stream(aS),d5-d6/a5 - /* Now decode the compressed data stream up to EOB */ -decode_loop: - lea o_litlen_tree(aS),a0 - /* START OF HOT LOOP */ -2: INLINE_stream_next_symbol /* litlen_sym */ -#if OPT_TABLE_LOOKUP - cmp.w d4,d0 /* 4 cy (d4.w = 256) */ -#else - cmp.w #256,d0 /* 8 cy */ -#endif - jcc 2f /* 8 cy */ - /* 0-255: Byte literal */ - move.b d0,(a4)+ /* 8 cy */ - jra 2b /* 10 cy */ - /* END OF HOT LOOP -- 30 + ~108 + [34] = ~160 CYCLES */ -9: /* 256: End-of-block: we're done */ - lea o_frame(aS),aS - rts -2: jeq 9b - /* 257+: pair */ -#if !OPT_TABLE_LOOKUP /* Already shifted in case of OPT_TABLE_LOOKUP */ - lsl.w #2,d0 -#endif - lea o_length_extra-257*4(aS),a2 - add.w d0,a2 - move.w (a2)+,d1 - INLINE_stream_next_bits - add.w (a2),d0 - move.w d0,d3 /* d3 = cplen */ - lea o_dist_tree(aS),a0 - INLINE_stream_next_symbol /* dist_sym */ -#if !OPT_TABLE_LOOKUP /* Already shifted in case of OPT_TABLE_LOOKUP */ - lsl.w #2,d0 -#endif - lea o_dist_extra(aS),a2 - add.w d0,a2 - move.w (a2)+,d1 - INLINE_stream_next_bits - add.w (a2),d0 /* d0 = cpdst */ - move.l a4,a0 - sub.w d0,a0 /* a0 = outp - cpdst */ -#if OPT_UNROLL_COPY_LOOP - lsr.w #1,d3 - jcs 4f - subq.w #1,d3 -3: move.b (a0)+,(a4)+ -4: move.b (a0)+,(a4)+ -#else - subq.w #1,d3 -3: move.b (a0)+,(a4)+ -#endif - dbf d3,3b - jra decode_loop - -#if !OPT_INLINE_FUNCTIONS -stream_next_symbol: - STREAM_NEXT_SYMBOL - rts -#endif - - /* Build a base/extra-bits table on the stack. - * d0 = #pairs-1, d2 = max_value, d4 = log_2(extrabits_repeat) */ -build_base_extrabits: -#if !OPT_STORAGE_OFFSTACK - move.l (sp)+,a0 -#endif -1: move.w d0,d3 - lsr.w d4,d3 - subq.w #1,d3 - jcc 2f - moveq #0,d3 -2: moveq #0,d1 - bset d3,d1 /* d1 = 1 << extrabits */ - sub.w d1,d2 /* d2 = base */ - move.w d2,-(aS) - move.w d3,-(aS) - dbf d0,1b -#if !OPT_STORAGE_OFFSTACK - jmp (a0) -#else - rts -#endif - -dispatch: /* Decoder dispatch table. */ - dc.b uncompressed_block - uncompressed_block - dc.b static_huffman - uncompressed_block - dc.b dynamic_huffman - uncompressed_block - -codelen_order: /* Order of code lengths for the code length alphabet. */ - dc.b 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - - /* a4 = output, a5 = input, all regs preserved - * a6 = *end* of storage area (only if OPT_STORAGE_OFFSTACK) */ -_inflate: - movem.l SAVE_RESTORE_REGS,-(aS) - - /* Build the base/extra-bits table */ - move.l #258,d2 - move.l d2,-(aS) - addq.w #1,d2 - moveq #27,d0 - moveq #2,d4 - jbsr build_base_extrabits - - /* Build the base/extra-bits table */ - move.w #32769,d2 - moveq #29,d0 - moveq #1,d4 - jbsr build_base_extrabits - - /* Initialise the stream */ - moveq #0,d5 /* d5 = stream: fetched data */ - moveq #0,d6 /* d6 = stream: nr fetched bits */ - -1: /* Process a block: Grab the BTYPE|BFINAL 3-bit code */ - moveq #3,d1 - jbsr stream_next_bits - move.l d0,-(aS) - /* Dispatch to the correct decoder for this block */ - lsr.b #1,d0 - move.b dispatch(pc,d0.w),d0 - lea uncompressed_block(pc),a0 - jsr (a0,d0.w) - /* Keep going until we see BFINAL=1 */ - move.l (aS)+,d0 - lsr.b #1,d0 - jcc 1b - - /* Pop the base/extra-bits lookup tables */ - lea (30+29)*4(aS),aS - - movem.l (aS)+,SAVE_RESTORE_REGS - rts - -#if OPT_PREGENERATE_TABLES -pregen_static_huffman: - lea -o_frame(aS),aS /* frame pre-generated; skip over it */ - move.w #256,d4 - jra decode_loop -pregen_dynamic_huffman: - move.l (aS),d0 - lea -3000(aS),aS /* move to dynamic-huffman frame */ - move.l d0,(aS) /* copy o_mode into it */ - jbsr dynamic_huffman - lea 3000(aS),aS - rts - - /* Pre-generate conversion tables for Inflate. */ - /* a6 = Pointer to end of 6000-byte block of memory to contain - * pre-generated tables. All registers preserved. */ -inflate_gentables: - movem.l a5-a6,-(sp) - lea pregen_dummy_block(pc),a5 - jbsr inflate /* static block */ - lea -3000(aS),aS - lea pregen_dummy_block(pc),a5 - jbsr inflate /* dynamic block */ - movem.l (sp)+,a5-a6 - rts - - /* Inflate, using pre-generated tables. */ - /* a4 = output, a5 = input, all regs preserved - * a6 = *end* of 6000-byte pre-generated storage area */ -inflate_fromtables: - movem.l SAVE_RESTORE_REGS,-(aS) - - /* Skip the pre-generated base/extra-bits lookup tables */ - lea -(30+29)*4(aS),aS - - /* Initialise the stream */ - moveq #0,d5 /* d5 = stream: fetched data */ - moveq #0,d6 /* d6 = stream: nr fetched bits */ - -1: /* Process a block: Grab the BTYPE|BFINAL 3-bit code */ - moveq #3,d1 - jbsr stream_next_bits - move.l d0,-(aS) - /* Dispatch to the correct decoder for this block */ - and.b #0xfe,d0 - move.w pregen_dispatch(pc,d0.w),d0 - lea uncompressed_block(pc),a0 - jsr (a0,d0.w) - /* Keep going until we see BFINAL=1 */ - move.l (aS)+,d0 - lsr.b #1,d0 - jcc 1b - - /* Pop the base/extra-bits lookup tables */ - lea (30+29)*4(aS),aS - - movem.l (aS)+,SAVE_RESTORE_REGS - rts - -pregen_dispatch: - dc.w uncompressed_block - uncompressed_block - dc.w pregen_static_huffman - uncompressed_block - dc.w pregen_dynamic_huffman - uncompressed_block -pregen_dummy_block: /* A single static block containing EOB symbol only */ - dc.b 0x03,0x00 -#endif /* OPT_PREGENERATE_TABLES */ - -#undef o_hdist -#undef o_hlit -#undef o_lens -#undef o_codelen_tree -#undef o_litlen_tree -#undef o_dist_tree -#undef o_frame diff --git a/utilities/stateload/main.c b/utilities/stateload/main.c deleted file mode 100644 index 84cd3a05..00000000 --- a/utilities/stateload/main.c +++ /dev/null @@ -1,1657 +0,0 @@ - -/* Real hardware UAE state file loader */ -/* Copyright 2019 Toni Wilen */ - -#define VER "2.0 BETA #1" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "header.h" - -extern struct GfxBase *GfxBase; -extern struct DosLibrary *DosBase; - -static const UBYTE *const version = "$VER: ussload " VER " (" REVDATE ")"; - -static const char *const chunknames[] = -{ - "ASF ", - "CPU ", "CHIP", "AGAC", - "CIAA", "CIAB", "ROM ", - "DSK0", "DSK1", "DSK2", "DSK3", - "AUD0", "AUD1", "AUD2", "AUD3", - "END ", - NULL -}; -static const char *const memchunknames[] = -{ - "CRAM", "BRAM", "FRAM", - NULL -}; -static const char *const unsupportedchunknames[] = -{ - "FRA2", "FRA3", "FRA4", - "ZRA2", "ZRA3", "ZRA4", - "ZCRM", "PRAM", - "A3K1", "A3K2", - "BORO", "P96 ", - "FSYC", - NULL -}; - -static ULONG getlong(UBYTE *chunk, int offset) -{ - ULONG v; - - chunk += offset; - v = (chunk[0] << 24) | (chunk[1] << 16) | (chunk[2] << 8) | (chunk[3] << 0); - return v; -} -static ULONG getword(UBYTE *chunk, int offset) -{ - ULONG v; - - chunk += offset; - v = (chunk[0] << 8) | (chunk[1] << 0); - return v; -} - -static void set_agacolor(UBYTE *p) -{ - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - - int aga = (c->vposr & 0x0f00) == 0x0300; - if (!aga) - return; - - for (int i = 0; i < 8; i++) { - for (int k = 0; k < 2; k++) { - c->bplcon3 = (i << 13) | (k ? (1 << 9) : 0); - for (int j = 0; j < 32; j++) { - ULONG c32 = getlong(p, (j + i * 32) * 4); - if (!k) - c32 >>= 4; - // R1R2G1G2B1B2 -> R2G2B2 - UWORD col = ((c32 & 0x00000f) << 0) | ((c32 & 0x000f00) >> 4) | ((c32 & 0x0f0000) >> 8); - if (!k && (c32 & 0x80000000)) - col |= 0x8000; // genlock transparency bit - c->color[j] = col; - } - } - } - c->bplcon3 = 0x0c00; -} - -static void wait_lines(WORD lines) -{ - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - - UWORD line = c->vhposr & 0xff00; - while (lines-- > 0) { - for (;;) { - UWORD line2 = c->vhposr & 0xff00; - if (line == line2) - continue; - line = line2; - break; - } - } -} - -static void step_floppy(void) -{ - volatile struct CIA *ciab = (volatile struct CIA*)0xbfd000; - ciab->ciaprb &= ~CIAF_DSKSTEP; - // delay - ciab->ciaprb &= ~CIAF_DSKSTEP; - ciab->ciaprb |= CIAF_DSKSTEP; - wait_lines(200); -} - -static void reset_floppy(struct uaestate *st) -{ - volatile struct CIA *ciab = (volatile struct CIA*)0xbfd000; - - // all drives motor off - ciab->ciaprb = 0xff; - // select all - ciab->ciaprb &= ~(15 << 3); - // deselect all - ciab->ciaprb |= 15 << 3; -} - -static void set_floppy(UBYTE *p, ULONG num) -{ - ULONG id = getlong(p, 0); - UBYTE state = p[4]; - UBYTE track = p[5]; - - // drive disabled? - if (state & 2) - return; - // invalid track? - if (track >= 80) - return; - - volatile struct CIA *ciaa = (volatile struct CIA*)0xbfe001; - volatile struct CIA *ciab = (volatile struct CIA*)0xbfd000; - - ciab->ciaprb = 0xff; - - // motor on? - if (state & 1) { - ciab->ciaprb &= ~CIAF_DSKMOTOR; - } - // select drive - ciab->ciaprb &= ~(CIAF_DSKSEL0 << num); - - wait_lines(100); - int seekcnt = 80; - while (seekcnt-- > 0) { - if (!(ciaa->ciapra & CIAF_DSKTRACK0)) - break; - step_floppy(); - } - wait_lines(100); - if (seekcnt <= 0) { - // no track0 after 80 steps: drive missing or not responding - ciab->ciaprb |= CIAF_DSKMOTOR; - ciab->ciaprb |= CIAF_DSKSEL0 << num; - return; - } - - ciab->ciaprb &= ~CIAF_DSKDIREC; - wait_lines(800); - for (UBYTE i = 0; i < track; i++) { - step_floppy(); - } - - ciab->ciaprb |= CIAF_DSKSEL0 << num; -} - -// current AUDxLEN and AUDxPT -static void set_audio(UBYTE *p, ULONG num) -{ - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - ULONG l; - c->aud[num].ac_vol = p[1]; // AUDxVOL - c->aud[num].ac_per = getword(p, 1 + 1 + 1 + 1 + 2 + 2 + 2); // AUDxPER - c->aud[num].ac_len = getword(p, 1 + 1 + 1 + 1 + 2); // AUDxLEN - l = getword(p, 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 + 2 + 2) << 16; // AUDxLCH - l |= getword(p, 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 + 2 + 2 + 2); // AUDxLCL - c->aud[num].ac_ptr = (UWORD*)l; -} - -// latched AUDxLEN and AUDxPT -void set_audio_final(struct uaestate *st) -{ - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - for (UWORD num = 0; num < 4; num++) { - UBYTE *p = st->audio_chunk[num]; - ULONG l; - c->aud[num].ac_len = getword(p, 1 + 1 + 1 + 1); // AUDxLEN - l = getword(p, 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2) << 16; // AUDxLCH - l |= getword(p, 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 + 2); // AUDxLCL - c->aud[num].ac_ptr = (UWORD*)l; - } -} - -static void set_sprite(UBYTE *p, ULONG num) -{ - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - ULONG l; - - l = getword(p, 0) << 16; // SPRxPTH - l |= getword(p, 2); // SPRxPTL - c->sprpt[num] = (APTR)l; - c->spr[num].pos = getword(p, 2 + 2); // SPRxPOS - c->spr[num].ctl = getword(p, 2 + 2 + 2); // SPRxCTL -} - -static void set_custom(struct uaestate *st) -{ - volatile UWORD *c = (volatile UWORD*)0xdff000; - UBYTE *p = st->custom_chunk; - p += 4; - for (WORD i = 0; i < 0x1fe; i += 2, c++) { - - // sprites - if (i >= 0x120 && i < 0x180) - continue; - - // audio - if (i >= 0xa0 && i < 0xe0) - continue; - - // skip blitter start, DMACON, INTENA, registers - // that are write strobed, unused registers, - // read-only registers. - switch(i) - { - case 0x00: - case 0x02: - case 0x04: - case 0x06: - case 0x08: - case 0x10: - case 0x16: - case 0x18: - case 0x1a: - case 0x1c: - case 0x1e: - case 0x24: // DSKLEN - case 0x26: - case 0x28: - case 0x2a: // VPOSW - case 0x2c: // VHPOSW - case 0x30: - case 0x38: - case 0x3a: - case 0x3c: - case 0x3e: - case 0x58: - case 0x5a: - case 0x5e: - case 0x68: - case 0x6a: - case 0x6c: - case 0x6e: - case 0x76: - case 0x78: - case 0x7a: - case 0x7c: - case 0x88: - case 0x8a: - case 0x8c: - case 0x96: // DMACON - case 0x9a: // INTENA - case 0x9c: // INTREQ - p += 2; - continue; - } - - // skip programmed sync registers except BEAMCON0 - // skip unused registers - if (i >= 0x1c0 && i < 0x1fc && i != 0x1e4 && i != 0x1dc) { - p += 2; - continue; - } - - UWORD v = getword(p, 0); - p += 2; - - // diwhigh - if (i == 0x1e4) { - // diwhigh_written not set? skip. - if (!(v & 0x8000)) - continue; - v &= ~0x8000; - } - - // BEAMCON0: PAL/NTSC only - if (i == 0x1dc) { - if (st->flags & FLAGS_FORCEPAL) - v = 0x20; - else if (st->flags & FLAGS_FORCENTSC) - v = 0x00; - v &= 0x20; - } - - // ADKCON - if (i == 0x9e) { - v |= 0x8000; - } - - *c = v; - } -} - -void set_custom_final(UBYTE *p) -{ - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - c->intena = 0x7fff; - c->intreq = 0x7fff; - c->vposw = (getword(p, 4 + 0x04) & 0x8000) | (c->vposr & 7); // set LOF - c->dmacon = getword(p, 4 + 0x96) | 0x8000; - c->intena = getword(p, 4 + 0x9a) | 0x8000; - c->intreq = getword(p, 4 + 0x9c) | 0x8000; -} - -static void set_cia(UBYTE *p, ULONG num) -{ - volatile struct CIA *cia = (volatile struct CIA*)(num ? 0xbfd000 : 0xbfe001); - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - - cia->ciacra &= ~(CIACRAF_START | CIACRAF_RUNMODE); - cia->ciacrb &= ~(CIACRBF_START | CIACRBF_RUNMODE); - volatile UBYTE dummy = cia->ciaicr; - cia->ciaicr = 0x7f; - c->intreq = 0x7fff; - - p[14] &= ~CIACRAF_LOAD; - p[15] &= ~CIACRAF_LOAD; - - UBYTE flags = p[16 + 1 + 2 * 2 + 3 + 3]; - - cia->ciapra = p[0]; - cia->ciaprb = p[1]; - cia->ciaddra = p[2]; - cia->ciaddrb = p[3]; - - // load timers - cia->ciatalo = p[4]; - cia->ciatahi = p[5]; - cia->ciatblo = p[6]; - cia->ciatbhi = p[7]; - cia->ciacra |= CIACRAF_LOAD; - cia->ciacrb |= CIACRBF_LOAD; - // load timer latches - cia->ciatalo = p[16 + 1]; - cia->ciatahi = p[16 + 2]; - cia->ciatblo = p[16 + 3]; - cia->ciatbhi = p[16 + 4]; - - // load alarm - UBYTE *alarm = &p[16 + 1 + 2 * 2 + 3]; - cia->ciacrb |= CIACRBF_ALARM; - if (flags & 2) { - // leave latched - cia->ciatodlow = alarm[0]; - cia->ciatodmid = alarm[1]; - cia->ciatodhi = alarm[2]; - } else { - cia->ciatodhi = alarm[2]; - cia->ciatodmid = alarm[1]; - cia->ciatodlow = alarm[0]; - } - cia->ciacrb &= ~CIACRBF_ALARM; - - // load tod - UBYTE *tod = &p[8]; - if (flags & 1) { - // leave latched - cia->ciatodlow = tod[0]; - cia->ciatodmid = tod[1]; - cia->ciatodhi = tod[2]; - } else { - cia->ciatodhi = tod[2]; - cia->ciatodmid = tod[1]; - cia->ciatodlow = tod[0]; - } -} - -void set_cia_final(UBYTE *p, ULONG num) -{ - volatile struct CIA *cia = (volatile struct CIA*)(num ? 0xbfd000 : 0xbfe001); - volatile UBYTE dummy = cia->ciaicr; - cia->ciaicr = p[16] | CIAICRF_SETCLR; -} - -static void free_allocations(struct uaestate *st) -{ - for (int i = st->num_allocations - 1; i >= 0; i--) { - struct Allocation *a = &st->allocations[i]; - if (a->mh) { - Deallocate(a->mh, a->addr, a->size); - } else { - FreeMem(a->addr, a->size); - } - } -} - -static struct Allocation *add_allocation(void *addr, ULONG size, struct uaestate *st) -{ - if (st->num_allocations >= ALLOCATIONS) { - printf("ERROR: Too many allocations!\n"); - return NULL; - } - struct Allocation *a = &st->allocations[st->num_allocations++]; - a->addr = addr; - a->size = size; - return a; -} - -static ULONG mmu_remap(ULONG addr, ULONG size, BOOL wp, struct uaestate *st) -{ - if (!st->canusemmu) - return 0; - void *phys = AllocMem(size + 4095, MEMF_FAST); - if (!phys) { - printf("MMU: Error allocating remap space for %08lx-%08lx.\n", addr, addr + size - 1); - return 0; - } - Forbid(); - FreeMem(phys, size + 4095); - ULONG alignedphys = (((ULONG)phys) + 4095) & ~4095; - phys = AllocAbs(size, (void*)alignedphys); - Permit(); - if (!phys) - return 0; - if (!map_region(st, (void*)addr, phys, size, FALSE, wp, FALSE, 0)) { - FreeMem(phys, size); - return 0; - } - add_allocation(phys, size, st); - st->mmuused++; - return alignedphys; -} - -UBYTE *allocate_abs(ULONG size, ULONG addr, struct uaestate *st) -{ - UBYTE *b = AllocAbs(size, (APTR)addr); - if (b) { - add_allocation(b, size, st); - return b; - } - return NULL; -} - -static UBYTE *extra_allocate(ULONG size, struct uaestate *st) -{ - UBYTE *b; - - for (;;) { - b = AllocAbs(size, st->extra_mem_pointer); - if (b) { - add_allocation(b, size, st); - st->extra_mem_pointer += (size + 7) & ~7; - return b; - } - st->extra_mem_pointer += 8; - if (st->extra_mem_pointer + size >= st->extra_ram + st->extra_ram_size) - return NULL; - } -} - -// allocate from extra mem -static UBYTE *tempmem_allocate(ULONG size, struct uaestate *st) -{ - UBYTE *b = NULL; - if (st->extra_mem_head) { - b = Allocate(st->extra_mem_head, size); - if (b) { - struct Allocation *a = add_allocation(b, size, st); - if (a) - a->mh = st->extra_mem_head; - } - } - if (!b) { - b = extra_allocate(size, st); - } - return b; -} - -// allocate from statefile reserved bank index -static UBYTE *tempmem_allocate_reserved(ULONG size, WORD index, struct uaestate *st) -{ - struct MemoryBank *mb = &st->membanks[index]; - if (!mb->targetsize) - return NULL; - UBYTE *addr = mb->targetaddr; - for (;;) { - addr += 32768; - if (addr - mb->targetaddr + size >= mb->targetsize) - return NULL; - UBYTE *b = AllocAbs(size, addr); - if (b) { - add_allocation(b, size, st); - return b; - } - } -} - -static void copyrom(ULONG addr, struct uaestate *st) -{ - ULONG *dst = (ULONG*)addr; - ULONG *src = (ULONG*)st->maprom; - UWORD cnt = st->mapromsize / 16; - for (UWORD i = 0; i < cnt; i++) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - } - if (st->mapromsize == 262144) { - src = (ULONG*)st->maprom; - for (UWORD i = 0; i < cnt; i++) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - } - } -} - -static void set_maprom(struct uaestate *st) -{ - struct mapromdata *mrd = &st->mrd[1]; - if (mrd->type == MAPROM_ACA500 || mrd->type == MAPROM_ACA500P) { - volatile UBYTE *base = (volatile UBYTE*)mrd->board; - base[0x3000] = 0; - base[0x7000] = 0; - base[0xf000] = 0; - base[0xb000] = 0; - base[0x23000] = 0; - copyrom(mrd->addr, st); - base[0x23000] = 0xff; - base[0x3000] = 0; - } - mrd = &st->mrd[0]; - if (mrd->type == MAPROM_ACA1221EC) { - volatile UBYTE *base = (volatile UBYTE*)mrd->board; - base[0x1000] = 0x05; - base[0x1001] = 0x00; - base[0x2000] = 0x00; - base[0x1000] = 0x03; - base[0x1001] = 0x01; - base[0x2000] = 0x00; - copyrom(0x600000, st); - copyrom(0x780000, st); - base[0x1000] = 0x03; - base[0x1001] = 0x00; - base[0x2000] = 0x00; - base[0x1000] = 0x05; - base[0x1001] = 0x01; - base[0x2000] = 0x00; - } - if (mrd->type == MAPROM_ACA12xx) { - ULONG mapromaddr = mrd->addr; - volatile UWORD *base = (volatile UWORD*)mrd->board; - base[0 / 2] = 0xffff; - base[4 / 2] = 0x0000; - base[8 / 2] = 0xffff; - base[12 / 2] = 0xffff; - base[0x18 / 2] = 0x0000; // maprom off - copyrom(mapromaddr, st); - copyrom(mapromaddr + 524288, st); - base[0x18 / 2] = 0xffff; // maprom on - volatile UWORD dummy = base[0]; - } - if (mrd->type == MAPROM_ACA1233N) { - volatile UWORD *base = (volatile UWORD*)mrd->board; - ULONG mapromaddr = mrd->addr; - volatile UWORD dummy = base[0]; - base[0x00 / 2] = 0xffff; // s unlock 0 - base[0x02 / 2] = 0xffff; // s unlock 1 - base[0x20 / 2] = 0xffff; // c unlock 0 - base[0x04 / 2] = 0xffff; // s unlock 2 - base[0x22 / 2] = 0xffff; // c unlock 1 - base[0x06 / 2] = 0xffff; // s unlock 3 - // maprom off - base[0x28 / 2] = 0xffff; - if (mrd->config) { - // maprom overlay on - for(int i = 0; i < 6; i++) - base[0x1c / 2] = 0xffff; - base[0x1a / 2] = 0xffff; - } - copyrom(mapromaddr, st); - copyrom(mapromaddr + 524288, st); - if (mrd->config) { - // maprom overlay off - base[0x3a / 2] = 0xffff; - } - // maprom on - base[0x08 / 2] = 0xffff; - } - if (mrd->type == MAPROM_GVP) { - copyrom(mrd->addr, st); - volatile UWORD *base = (volatile UWORD*)mrd->board; - *base = (UWORD)mrd->config; - } - if (mrd->type == MAPROM_BLIZZARD12x0) { - copyrom(mrd->addr, st); - volatile UBYTE *base = (volatile UBYTE*)mrd->board; - *base = (UBYTE)mrd->config; - } - if (mrd->type == MAPROM_MMU) { - copyrom(mrd->addr, st); - } -} - -static BOOL has_maprom_blizzard(struct uaestate *st) -{ - struct mapromdata *mrd = &st->mrd[0]; - struct ConfigDev *cd; - // 1230MKIV/1240/1260 - cd = (struct ConfigDev*)FindConfigDev(0, 8512, 17); - if (cd) { - mrd->type = MAPROM_BLIZZARD12x0; - mrd->addr = 0x4ff80000; - } - // 1230MKIII - cd = (struct ConfigDev*)FindConfigDev(0, 8512, 13); - if (cd) { - mrd->type = MAPROM_BLIZZARD12x0; - mrd->addr = 0x1ef80000; - } - // 1230MKI/II - cd = (struct ConfigDev*)FindConfigDev(0, 8512, 11); - if (cd) { - mrd->type = MAPROM_BLIZZARD12x0; - mrd->addr = 0x0ff80000; - } - mrd->board = (APTR)0x80ffff00; - mrd->config = 0x42; - if (st->debug && mrd->type) - printf("Blizzard12x0 MapROM %08lx\n", mrd->addr); - return mrd->type != 0; -} - - -static const ULONG gvp_a530[] = -{ - 0x00a00000, 14, - 0x00600000, 10, - 0x00400000, 12, - 0x00300000, 8, - 0 -}; -static const ULONG gvp_gforce030[] = -{ - 0x02000000, 10, - 0x01c00000, 12, - 0x01800000, 8, - 0x01400000, 6, - 0x00a00000, 2, - 0x00600000, 4, - 0 -}; -static const ULONG gvp_gforce2k_040[] = -{ - 0x05000000, 8, - 0x04000000, 12, - 0x03000000, 10, - 0x02000000, 14, - 0x01c00000, 10, - 0x01800000, 12, - 0 -}; -#if 0 -static const ULONG gvp_gforce3k_040[] = -{ - 0x08800000, 0xC0000000, - 0x08400000, 0x80000000, - 0 -}; -#endif - -static BOOL has_maprom_gvp(struct uaestate *st) -{ - struct mapromdata *mrd = &st->mrd[0]; - struct ConfigDev *cd = (struct ConfigDev*)FindConfigDev(0, 2017, 11); - if (!cd) - return FALSE; - UBYTE v = *((volatile UBYTE*)cd->cd_BoardAddr + 0x8001); - if (st->debug) - printf("GVP ID=%02x\n", v); - const ULONG *gvpmaprom = NULL; - switch(v & 0xf8) - { - case 0x20: - case 0x30: - gvpmaprom = gvp_gforce2k_040; - break; - case 0x60: - case 0x70: - case 0xe0: - case 0xf0: - gvpmaprom = gvp_gforce030; - break; - case 0xc0: - case 0xd0: - gvpmaprom = gvp_a530; - break; - case 0x40: - break; - } - if (!gvpmaprom) - return FALSE; - Forbid(); - struct MemHeader *mh = (struct MemHeader*)SysBase->MemList.lh_Head; - while (mh->mh_Node.ln_Succ && !mrd->type) { - ULONG mend = ((((ULONG)mh->mh_Upper) + 0xffff) & 0xffff0000); - for (int i = 0; gvpmaprom[i]; i += 2) { - if (gvpmaprom[i] == mend) { - mrd->type = MAPROM_GVP; - mrd->addr = mend - 524288; - mrd->config = gvpmaprom[i + 1]; - mrd->board = cd->cd_BoardAddr + 0x68; - // ignore return value, maprom may be already enabled - allocate_abs(524288, mrd->addr, st); - break; - } - } - mh = (struct MemHeader*)mh->mh_Node.ln_Succ; - } - Permit(); - if (st->debug) - printf("GVP Map ROM=%08lx\n", mrd->addr); - return mrd->type != 0; -} - -static BOOL has_maprom_aca(struct uaestate *st) -{ - if (OpenResource("aca.resource")) { - struct mapromdata *mrd2 = &st->mrd[1]; - // ACA500(+) - volatile UBYTE *base = (volatile UBYTE*)0xb00000; - Disable(); - base[0x3000] = 0; - base[0x7000] = 0; - base[0xf000] = 0; - base[0xb000] = 0; - UBYTE id = 0; - if (base[0x13000] & 0x80) - id |= 0x08; - if (base[0x17000] & 0x80) - id |= 0x04; - if (base[0x1b000] & 0x80) - id |= 0x02; - if (base[0x1f000] & 0x80) - id |= 0x01; - if (id == 7) { - mrd2->type = MAPROM_ACA500; - mrd2->addr = 0x980000; - } else if (id == 8 || id == 9) { - mrd2->type = MAPROM_ACA500P; - mrd2->addr = 0xa00000; - } - mrd2->board = (APTR)base; - base[0x3000] = 0; - Enable(); - if (st->debug) - printf("ACA500/ACA500plus ID=%02x\n", id); - } - struct mapromdata *mrd = &st->mrd[0]; - if (FindConfigDev(0, 0x1212, 33) || FindConfigDev(0, 0x1212, 68)) { - // ACA1233n 68030 - mrd->type = MAPROM_ACA1233N; - mrd->addr = 0x47f00000; - mrd->board = (APTR)0x47e8f000; - mrd->config = 0; - } else if (FindConfigDev(0, 0x1212, 32) || FindConfigDev(0, 0x1212, 72)) { - // ACA1233n 68EC020 - if ((ULONG)has_maprom_aca >= 0x200000) { - mrd->type = MAPROM_ACA1233N; - mrd->addr = 0x100000; - mrd->board = (APTR)0xb8f000; - mrd->config = 1; - st->maprom_memlimit |= 1 << MB_CHIP; - } - } else if (FindConfigDev(0, 0x1212, 0x16)) { - // ACA1221EC - mrd->type = MAPROM_ACA1221EC; - mrd->addr = 0x780000; - mrd->board = (APTR)0xe90000; - // we can't use 0x200000 because it goes away when setting up maprom.. - mrd->memunavailable = 0x00200000; - } else if (TypeOfMem((APTR)0x0bd80000)) { // at least 62M - // This test should be better.. - // perhaps it is ACA12xx - Disable(); - volatile UWORD *base = (volatile UWORD*)0xb8f000; - volatile UWORD dummy = base[0]; - // unlock - base[0 / 2] = 0xffff; - base[4 / 2] = 0x0000; - base[8 / 2] = 0xffff; - base[12 / 2] = 0xffff; - UBYTE id = 0; - volatile UWORD *idbits = base + 4 / 2; - for (UWORD i = 0; i < 5; i++) { - id <<= 1; - if (idbits[0] & 1) - id |= 1; - idbits += 4 / 2; - } - UWORD mrtest = 0; - if (id != 0 && id != 31) { - // test that maprom bit sticks - UWORD oldmr = base[0x18 / 2]; - base[0x18 / 2] = 0xffff; - dummy = base[0]; - mrtest = (base[0x18 / 2] & 0x8000) != 0; - base[0 / 2] = 0xffff; - base[4 / 2] = 0x0000; - base[8 / 2] = 0xffff; - base[12 / 2] = 0xffff; - base[0x18 / 2] = oldmr; - } - dummy = base[0]; - Enable(); - if (st->debug) - printf("ACA12xx ID=%02x. MapROM=%d\n", id, mrtest); - ULONG mraddr = 0; - if (mrtest) { - if (TypeOfMem((APTR)0x0bf00000)) { - if (!TypeOfMem((APTR)0x0fe80000)) { - mrd->type = MAPROM_ACA12xx; - mrd->addr = 0x0ff00000; - } - } else { - mrd->type = MAPROM_ACA12xx; - mrd->addr = 0x0bf00000; - } - } - mrd->board = (APTR)base; - } - return st->mrd[0].type != 0; -} - -static BOOL has_maprom_mmu(struct uaestate *st) -{ - if (!st->canusemmu) - return FALSE; - struct mapromdata *mrd = &st->mrd[0]; - unmap_region(st, (void*)0xf80000, 524288); - mrd->addr = mmu_remap(0xf80000, 524288, FALSE, st); - if (mrd->addr) { - mrd->type = MAPROM_MMU; - return TRUE; - } - return FALSE; -} - -static BOOL has_maprom(struct uaestate *st) -{ - if (!st->usemaprom) - return -1; - for (;;) { - if (has_maprom_mmu(st)) - break; - if (has_maprom_aca(st)) - break; - if (has_maprom_gvp(st)) - break; - if (!has_maprom_blizzard(st)) - break; - return FALSE; - } - if (st->debug) { - for (int i = 0; i < 2; i++) { - struct mapromdata *mrd = &st->mrd[i]; - if (mrd->type) - printf("MAPROM type %d. Addr=%08lx Board=%08lx Cfg=%08lx.\n", mrd->type, mrd->addr, mrd->board, mrd->config); - } - } - return st->mrd[0].type != 0 || st->mrd[1].type != 0; -} - -static void load_rom(struct uaestate *st) -{ - UBYTE rompath[100], rompath2[100]; - UBYTE *p; - - if (!st->mrd[0].type && !st->mrd[1].type) - return; - - sprintf(rompath, "DEVS:kickstarts/kick%d%03d.%s", st->romver, st->romrev, st->agastate ? "a1200" : "a500"); - p = rompath; - FILE *f = fopen(rompath, "rb"); - if (!f) { - sprintf(rompath2, "kick%d%03d.%s", st->romver, st->romrev, st->agastate ? "a1200" : "a500"); - f = fopen(rompath2, "rb"); - if (!f) { - printf("Couldn't open ROM image '%s'\n", rompath); - return; - } - p = rompath2; - } - fseek(f, 0, SEEK_END); - st->mapromsize = ftell(f); - fseek(f, 0, SEEK_SET); - if (!st->maprom && !(st->maprom_memlimit & (1 << MB_CHIP))) - st->maprom = tempmem_allocate_reserved(st->mapromsize, MB_CHIP, st); - if (!st->maprom && !(st->maprom_memlimit & (1 << MB_SLOW))) - st->maprom = tempmem_allocate_reserved(st->mapromsize, MB_SLOW, st); - if (!st->maprom) - st->maprom = tempmem_allocate(st->mapromsize, st); - if (!st->maprom) { - printf("Couldn't allocate %luk for ROM image '%s'.\n", st->mapromsize >> 10, p); - fclose(f); - return; - } - if (st->debug) - printf("MapROM temp %08lx\n", st->maprom); - if (fread(st->maprom, 1, st->mapromsize, f) != st->mapromsize) { - printf("Read error while reading map rom image '%s'\n", p); - fclose(f); - return; - } - fclose(f); - printf("ROM '%s' (%luk) loaded .\n", rompath, st->mapromsize >> 10); -} - -static void load_memory(FILE *f, WORD index, struct uaestate *st) -{ - struct MemoryBank *mb = &st->membanks[index]; - ULONG oldoffset = ftell(f); - ULONG chunksize = mb->size + 12; - fseek(f, mb->offset, SEEK_SET); - if (st->debug) - printf("Memory '%s', size %luk, offset %lu. Target %08lx.\n", mb->chunk, chunksize >> 10, mb->offset, mb->targetaddr); - // if Chip RAM and free space in another statefile block? Put it there because chip ram is decompressed first. - if (index == MB_CHIP) { - mb->addr = tempmem_allocate_reserved(chunksize, MB_SLOW, st); - if (!mb->addr) - mb->addr = tempmem_allocate_reserved(chunksize, MB_FAST, st); - } else if (index == MB_SLOW) { - mb->addr = tempmem_allocate_reserved(chunksize, MB_FAST, st); - } - if (!mb->addr) - mb->addr = tempmem_allocate(chunksize, st); - if (mb->addr) { - if (st->debug) - printf(" - Address %08lx - %08lx.\n", mb->addr, mb->addr + chunksize - 1); - if (fread(mb->addr, 1, chunksize, f) != chunksize) { - printf("ERROR: Read error (Chunk '%s', %lu bytes)\n", mb->chunk, chunksize); - st->errors++; - } - } else { - printf("ERROR: Out of memory (Chunk '%s', %lu bytes).\n", mb->chunk, chunksize); - st->errors++; - } - fseek(f, oldoffset, SEEK_SET); -} - -static int read_chunk_head(FILE *f, UBYTE *cnamep, ULONG *sizep, ULONG *flagsp) -{ - ULONG size = 0, flags = 0; - UBYTE cname[5]; - - *flagsp = 0; - *sizep = 0; - cnamep[0] = 0; - if (fread(cname, 1, 4, f) != 4) { - return 0; - } - cname[4] = 0; - strcpy(cnamep, cname); - - if (fread(&size, 1, 4, f) != 4) { - cnamep[0] = 0; - return 0; - } - - if (fread(&flags, 1, 4, f) == 0) { - return 1; - } - - if (size < 8) - return 1; - - if (size < 12) { - size = 0; - flags = 0; - } else { - size -= 12; - } - *sizep = size; - *flagsp = flags; - return 1; -} - -static UBYTE *load_chunk(FILE *f, UBYTE *cname, ULONG size, struct uaestate *st) -{ - UBYTE *b = NULL; - int acate = 0; - - //printf("Allocating %lu bytes for '%s'.\n", size, cname); - - b = tempmem_allocate(size, st); - - //printf("Reading chunk '%s', %lu bytes to address %08x\.n", cname, size, b); - - if (!b) { - printf("ERROR: Not enough memory (Chunk '%s', %ul bytes required).\n", cname, size); - return NULL; - } - - if (fread(b, 1, size, f) != size) { - printf("ERROR: Read error (Chunk '%s', %lu bytes).\n", cname, size); - return NULL; - } - - fseek(f, 4 - (size & 3), SEEK_CUR); - - return b; -} - -static UBYTE *read_chunk(FILE *f, UBYTE *cname, ULONG *sizep, ULONG *flagsp, struct uaestate *st) -{ - ULONG size, orgsize, flags; - - if (!read_chunk_head(f, cname, &size, &flags)) - return NULL; - orgsize = size; - *flagsp = flags; - - if (size == 0) - return NULL; - - ULONG maxsize = 0x7fffffff; - - for (int i = 0; unsupportedchunknames[i]; i++) { - if (!strcmp(cname, unsupportedchunknames[i])) { - printf("ERROR: Unsupported chunk '%s', %lu bytes, flags %08x.\n", cname, size, flags); - st->errors++; - return NULL; - } - } - - int found = 0; - for (int i = 0; chunknames[i]; i++) { - if (!strcmp(cname, chunknames[i])) { - found = 1; - if (st->debug) - printf("Reading chunk '%s', %lu bytes, flags %08x.\n", cname, size, flags); - break; - } - } - if (!found) { - // read only header if memory chunk - for (int i = 0; memchunknames[i]; i++) { - if (!strcmp(cname, memchunknames[i])) { - found = 1; - maxsize = 16; - if (st->debug) - printf("Checking memory chunk '%s', %lu bytes, flags %08x.\n", cname, size, flags); - break; - } - } - } - - if (!found) { - //printf("Skipped chunk '%s', %ld bytes, flags %08x\n", cname, size, flags); - fseek(f, size, SEEK_CUR); - if (size) - fseek(f, 4 - (size & 3), SEEK_CUR); - return NULL; - } - - *sizep = size; - if (size > maxsize) - size = maxsize; - UBYTE *chunk = malloc(size); - if (!chunk) { - printf("ERROR: Not enough memory (Chunk '%s', %lu bytes).\n", cname, size); - return NULL; - } - if (fread(chunk, 1, size, f) != size) { - printf("ERROR: Read error (Chunk '%s', %lu bytes)..\n", cname, size); - free(chunk); - return NULL; - } - if (orgsize > size) { - fseek(f, orgsize - size, SEEK_CUR); - } - fseek(f, 4 - (orgsize & 3), SEEK_CUR); - return chunk; -} - -static void find_extra_ram(struct uaestate *st) -{ - Forbid(); - struct MemHeader *mh = (struct MemHeader*)SysBase->MemList.lh_Head; - while (mh->mh_Node.ln_Succ) { - ULONG mstart = ((ULONG)mh->mh_Lower) & 0xffff0000; - ULONG msize = ((((ULONG)mh->mh_Upper) + 0xffff) & 0xffff0000) - mstart; - int i; - for (i = 0; i < MEMORY_REGIONS; i++) { - if (st->mem_allocated[i] == mh) - break; - } - if (i == MEMORY_REGIONS && (mstart != st->mrd[0].memunavailable && mstart != st->mrd[1].memunavailable)) { - if (msize > st->extra_ram_size) { - st->extra_ram = (UBYTE*)mstart; - st->extra_ram_size = msize; - st->extra_mem_head = mh; - } - } - mh = (struct MemHeader*)mh->mh_Node.ln_Succ; - } - Permit(); -} - -static ULONG check_ram(UBYTE *ramname, UBYTE *cname, UBYTE *chunk, WORD index, ULONG addr, ULONG offset, ULONG chunksize, ULONG flags, struct uaestate *st) -{ - ULONG size; - if (flags & 1) // compressed - size = getlong(chunk, 0); - else - size = chunksize; - if (st->debug) - printf("Statefile RAM: Address %08x, size %luk.\n", addr, size >> 10); - int found = 0; - ULONG mstart, msize; - Forbid(); - struct MemHeader *mh = (struct MemHeader*)SysBase->MemList.lh_Head; - while (mh->mh_Node.ln_Succ) { - mstart = ((ULONG)mh->mh_Lower) & 0xffff0000; - msize = ((((ULONG)mh->mh_Upper) + 0xffff) & 0xffff0000) - mstart; - if (mstart == addr) { - if (msize >= size) - found = 1; - else - found = -1; - break; - } - mh = (struct MemHeader*)mh->mh_Node.ln_Succ; - } - Permit(); - if (!found) { - // use MMU to create this address space if available - if (mmu_remap(addr, size, FALSE, st)) { - msize = size; - mstart = addr; - mh = NULL; - found = 1; - } else { - printf("ERROR: Required RAM address space %08x-%08x unavailable.\n", addr, addr + size - 1); - st->errors++; - return 0; - } - } - st->mem_allocated[index] = mh; - struct MemoryBank *mb = &st->membanks[index]; - mb->size = chunksize; - mb->offset = offset; - mb->targetaddr = (UBYTE*)addr; - mb->targetsize = msize; - mb->flags = flags; - strcpy(mb->chunk, cname); - if (st->debug) - printf("- Detected memory at %08x, total size %luk. Offset %ld.\n", mstart, msize >> 10, offset); - if (found > 0) { - if (st->debug) - printf("- Memory is usable (%luk required, %luk unused).\n", size >> 10, (msize - size) >> 10); - ULONG extrasize = msize - size; - if (extrasize >= 524288) { - if ((mstart >= 0x00200000 && st->extra_ram < (UBYTE*)0x00200000) || extrasize > st->extra_ram_size) { - st->extra_ram = (UBYTE*)(mstart + size); - st->extra_ram_size = extrasize; - } - } - return 1; - } - // if too small RAM area and not chip ram: mmu remap the missing part. - if (st->canusemmu) { - ULONG mmu_start = mstart + msize; - ULONG mmu_size = size - msize; - if (mmu_remap(mmu_start, mmu_size, FALSE, st)) { - printf("- MMU remapped missing address space %08x-%08x\n", mmu_start, mmu_start + mmu_size - 1); - if (mstart == 0) { - printf("- WARNING: Part of Chip RAM remapped, custom chipset can't access it!!\n"); - } - return 1; - } - } - printf("ERROR: Not enough %s RAM available. %luk required.\n", ramname, size >> 10); - st->errors++; - return 0; -} - -static void floppy_info(int num, UBYTE *p) -{ - UBYTE state = p[4]; - UBYTE track = p[5]; - if (state & 2) // disabled - return; - UBYTE *path = &p[4 + 1 + 1 + 1 + 1 + 4 + 4]; - printf("DF%d: Track %d ", num, track); - if (path[0]) - printf("'%s'.\n", path); - else - printf("\n"); -} - -static void check_rom(UBYTE *p, struct uaestate *st) -{ - UWORD ver = getword(p, 4 + 4 + 4); - UWORD rev = getword(p, 4 + 4 + 4 + 2); - - UWORD *rom = (UWORD*)0xf80000; - UWORD rver = rom[12 / 2]; - UWORD rrev = rom[14 / 2]; - - ULONG start = getlong(p, 0); - ULONG len = getlong(p, 4); - if (start == 0xf80000 && len == 262144) - start = 0xfc0000; - ULONG crc32 = getlong(p, 4 + 4 + 4 + 4); - - UBYTE *path = &p[4 + 4 + 4 + 4 + 4]; - while (*path++); - - int mismatch = ver != rver || rev != rrev; - if (mismatch) - printf("- WARNING: ROM version mismatch: %d.%d. System ROM: %d.%d\n", ver, rev, rver, rrev); - if (st->debug) - printf("ROM %08lx-%08lx %d.%d (CRC=%08x).\n", start, start + len - 1, ver, rev, crc32); - if (mismatch) { - if (st->debug) - printf("- '%s'\n", path); - st->romver = ver; - st->romrev = rev; - WORD mr = has_maprom(st); - if (mr == 0) { - if (st->debug) - printf("Map ROM support not detected\n"); - } else if (mr > 0) { - printf("- Map ROM hardware detected.\n"); - } - } -} - -static int parse_pass_2(FILE *f, struct uaestate *st) -{ - for (int i = 0; i < MEMORY_REGIONS; i++) { - struct MemoryBank *mb = &st->membanks[i]; - if (mb->size) { - load_memory(f, i, st); - } - } - if (st->romver) { - load_rom(st); - } - - for (;;) { - ULONG size, flags; - UBYTE cname [5]; - - if (!read_chunk_head(f, cname, &size, &flags)) { - return -1; - } - - if (!strcmp(cname, "END ")) - break; - - if (!strcmp(cname, "CPU ")) { - st->cpu_chunk = load_chunk(f, cname, size, st); - } else if (!strcmp(cname, "CHIP")) { - st->custom_chunk = load_chunk(f, cname, size, st); - } else if (!strcmp(cname, "AGAC")) { - st->aga_colors_chunk = load_chunk(f, cname, size, st); - } else if (!strcmp(cname, "CIAA")) { - st->ciaa_chunk = load_chunk(f, cname, size, st); - } else if (!strcmp(cname, "CIAB")) { - st->ciab_chunk = load_chunk(f, cname, size, st); - } else if (!strcmp(cname, "DSK0")) { - st->floppy_chunk[0] = load_chunk(f, cname, size, st); - floppy_info(0, st->floppy_chunk[0]); - } else if (!strcmp(cname, "DSK1")) { - st->floppy_chunk[1] = load_chunk(f, cname, size, st); - floppy_info(1, st->floppy_chunk[1]); - } else if (!strcmp(cname, "DSK2")) { - st->floppy_chunk[2] = load_chunk(f, cname, size, st); - floppy_info(2, st->floppy_chunk[2]); - } else if (!strcmp(cname, "DSK3")) { - st->floppy_chunk[3] = load_chunk(f, cname, size, st); - floppy_info(3, st->floppy_chunk[3]); - } else if (!strcmp(cname, "AUD0")) { - st->audio_chunk[0] = load_chunk(f, cname, size, st); - } else if (!strcmp(cname, "AUD1")) { - st->audio_chunk[1] = load_chunk(f, cname, size, st); - } else if (!strcmp(cname, "AUD2")) { - st->audio_chunk[2] = load_chunk(f, cname, size, st); - } else if (!strcmp(cname, "AUD3")) { - st->audio_chunk[3] = load_chunk(f, cname, size, st); - } else { - fseek(f, size, SEEK_CUR); - fseek(f, 4 - (size & 3), SEEK_CUR); - } - } - - return st->errors; -} - -static int parse_pass_1(FILE *f, struct uaestate *st) -{ - int first = 1; - UBYTE *b = NULL; - - for (;;) { - ULONG offset = ftell(f); - ULONG size, flags; - UBYTE cname[5]; - b = read_chunk(f, cname, &size, &flags, st); - if (!strcmp(cname, "END ")) - break; - if (!b) { - if (!cname[0]) - return -1; - continue; - } - - if (first) { - if (strcmp(cname, "ASF ")) { - printf("ERROR: Not UAE statefile.\n"); - return -1; - } - first = 0; - continue; - } - - if (!strcmp(cname, "CPU ")) { - ULONG smodel = 68000; - for (int i = 0; i < 4; i++) { - if (SysBase->AttnFlags & (1 << i)) - smodel += 10; - } - if (SysBase->AttnFlags & 0x80) - smodel = 68060; - ULONG model = getlong(b, 0); - printf("CPU: %lu.\n", model); - if (smodel != model) { - printf("- WARNING: %lu CPU statefile but system has %lu CPU.\n", model, smodel); - } - if (model > 68030) { - printf("- ERROR: Only 68000/68010/68020/68030 statefiles are supported.\n"); - st->errors++; - } - } else if (!strcmp(cname, "CHIP")) { - UWORD vposr = getword(b, 4 + 4); // VPOSR - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - UWORD svposr = c->vposr; - int aga = (vposr & 0x0f00) == 0x0300; - int ecs = (vposr & 0x2000) == 0x2000; - int ntsc = (vposr & 0x1000) == 0x1000; - int saga = (svposr & 0x0f00) == 0x0300; - int secs = (svposr & 0x2000) == 0x2000; - int sntsc = (svposr & 0x1000) == 0x1000; - printf("Chipset: %s %s (0x%04X).\n", aga ? "AGA" : (ecs ? "ECS" : "OCS"), ntsc ? "NTSC" : "PAL", vposr); - if (aga && !saga) { - printf("- WARNING: AGA statefile but system is OCS/ECS.\n"); - } - if (saga && !aga) { - printf("- WARNING: OCS/ECS statefile but system is AGA.\n"); - } - if (!sntsc && !secs && ntsc) { - printf("- WARNING: NTSC statefile but system is OCS PAL.\n"); - } - if (sntsc && !secs && !ntsc) { - printf("- WARNING: PAL statefile but system is OCS NTSC.\n"); - } - st->agastate = aga; - } else if (!strcmp(cname, "CRAM")) { - check_ram("Chip", cname, b, MB_CHIP, 0x000000, offset, size, flags, st); - } else if (!strcmp(cname, "BRAM")) { - check_ram("Slow", cname, b, MB_SLOW, 0xc00000, offset, size, flags, st); - } else if (!strcmp(cname, "FRAM")) { - check_ram("Fast", cname, b, MB_FAST, 0x200000, offset, size, flags, st); - } else if (!strcmp(cname, "ROM ")) { - check_rom(b, st); - } - - free(b); - b = NULL; - } - - if (!st->errors) { - find_extra_ram(st); - if (!st->extra_ram) { - printf("ERROR: At least 512k RAM not used by statefile required.\n"); - st->errors++; - } else { - if (st->debug) - printf("%luk extra RAM at %08x.\n", st->extra_ram_size >> 10, st->extra_ram); - st->extra_mem_pointer = st->extra_ram; - st->errors = 0; - } - } else { - printf("ERROR: Incompatible hardware configuration.\n"); - st->errors++; - } - - free(b); - - return st->errors; -} - -extern void runit(void*); -extern void callinflate(UBYTE*, UBYTE*); -extern void flushcache(void); - -static void handlerambank(struct MemoryBank *mb, struct uaestate *st) -{ - UBYTE *sa = mb->addr + 12; /* skip chunk header */ - if (mb->flags & 1) { - // skip decompressed size and zlib header - callinflate(mb->targetaddr, sa + 4 + 2); - } else { - ULONG *s = (ULONG*)sa; - ULONG *d = (ULONG*)mb->targetaddr; - for (int i = 0; i < mb->size / 4; i++) { - *d++ = *s++; - } - } -} - -// Interrupts are off, supervisor state -static void processstate(struct uaestate *st) -{ - volatile struct Custom *c = (volatile struct Custom*)0xdff000; - - reset_floppy(st); - - if (st->maprom && (st->mrd[0].type || st->mrd[1].type)) { - c->color[0] = 0x404; - set_maprom(st); - } - - for (int i = 0; i < MEMORY_REGIONS; i++) { - if (i == MB_CHIP) - c->color[0] = 0x400; - if (i == MB_SLOW) - c->color[0] = 0x040; - if (i == MB_FAST) - c->color[0] = 0x004; - struct MemoryBank *mb = &st->membanks[i]; - if (mb->addr) { - handlerambank(mb, st); - } - } - - c->color[0] = 0x440; - - // must be before set_cia - for (int i = 0; i < 4; i++) { - set_floppy(st->floppy_chunk[i], i); - } - - c->color[0] = 0x444; - - set_agacolor(st->aga_colors_chunk); - set_custom(st); - for (int i = 0; i < 4; i++) { - set_audio(st->audio_chunk[i], i); - } - for (int i = 0; i < 8; i++) { - set_sprite(st->sprite_chunk[i], i); - } - set_cia(st->ciaa_chunk, 0); - set_cia(st->ciab_chunk, 1); - - runit(st); -} - -static void take_over(struct uaestate *st) -{ - // Copy stack, variables and code to safe location - - UBYTE *tempsp = tempmem_allocate(TEMP_STACK_SIZE, st); - if (!tempsp) { - printf("Out of memory for temp stack (%lu bytes).\n", TEMP_STACK_SIZE); - return; - } - - struct uaestate *tempst = (struct uaestate*)tempmem_allocate(sizeof(struct uaestate), st); - if (!tempst) { - printf("Out of memory for temp state variables (%lu bytes).\n", sizeof(struct uaestate)); - return; - } - memcpy(tempst, st, sizeof(struct uaestate)); - - struct Process *me = (struct Process*)FindTask(0); - struct CommandLineInterface *cli = (struct CommandLineInterface*)((((ULONG)me->pr_CLI) << 2)); - if (!cli) { - printf("CLI == NULL?\n"); - return; - } - ULONG *module = (ULONG*)(cli->cli_Module << 2); - ULONG hunksize = module[-1] << 2; - UBYTE *newcode = tempmem_allocate(hunksize, st); - if (!newcode) { - printf("Out of memory for temp code (%lu bytes).\n", hunksize); - return; - } - memcpy(newcode, module, hunksize); - - // ugly relocation hack but jumps to other module (from asm.S) are always absolute.. - // TODO: process the executable after linking - UWORD *cp = (UWORD*)newcode; - for (int i = 0; i < hunksize / 2; i++) { - // JSR/JMP xxxxxxxx.L? - if (*cp == 0x4eb9 || *cp == 0x4ef9) { - ULONG *ap = (ULONG*)(cp + 1); - ULONG *app = (ULONG*)(*ap); - void *addr = (void*)app; - if (addr == runit || addr == callinflate) { - *ap = (ULONG)addr - (ULONG)module + (ULONG)newcode; - //printf("Relocated %08x: %08x -> %08x\n", cp, addr, *ap); - } - } - cp++; - } - - if (st->testmode) { - printf("Test mode finished. Exiting.\n"); - return; - } - - if (!st->nowait) { - if (st->debug) { - printf("Code=%08lx Stack=%08lx Data=%08lx. Press RETURN!\n", newcode, tempsp, tempst); - } else { - printf("Change floppy disk(s) now if needed. Press RETURN to start.\n"); - } - UBYTE b; - fread(&b, 1, 1, stdin); - Delay(100); // So that key release gets processed by AmigaOS - } - - if (SysBase->LibNode.lib_Version >= 37) { - flushcache(); - } - - if (GfxBase->LibNode.lib_Version >= 37) { - LoadView(NULL); - WaitTOF(); - WaitTOF(); - } - - OwnBlitter(); - WaitBlit(); - - // No turning back! - extern void *killsystem(UBYTE*, struct uaestate*, ULONG); - killsystem(tempsp + TEMP_STACK_SIZE, tempst, (ULONG)processstate - (ULONG)module + (ULONG)newcode); -} - -int main(int argc, char *argv[]) -{ - FILE *f; - UBYTE *b; - ULONG size; - UBYTE cname[5]; - struct uaestate *st; - - printf("ussload v" VER " (" REVDATE " " REVTIME ")\n"); - if (argc < 2) { - printf("Syntax: ussload (parameters)\n"); - printf("- nowait = don't wait for return key.\n"); - printf("- debug = enable debug output.\n"); - printf("- test = test mode.\n"); - printf("- nomaprom = do not use map rom.\n"); - printf("- nommu = do not use MMU (68030/68040/68060).\n"); - printf("- nocache = disable caches before starting (68020+)\n"); - printf("- pal/ntsc = set PAL or NTSC mode (ECS/AGA only)\n"); - return 0; - } - - f = fopen(argv[1], "rb"); - if (!f) { - printf("Couldn't open '%s'\n", argv[1]); - return 0; - } - - st = calloc(sizeof(struct uaestate), 1); - if (!st) { - printf("Out of memory.\n"); - return 0; - } - st->usemaprom = 1; - st->canusemmu = 1; - for(int i = 2; i < argc; i++) { - if (!stricmp(argv[i], "debug")) - st->debug = 1; - if (!stricmp(argv[i], "test")) - st->testmode = 1; - if (!stricmp(argv[i], "nowait")) - st->nowait = 1; - if (!stricmp(argv[i], "nomaprom")) - st->usemaprom = 0; - if (!stricmp(argv[i], "nommu")) - st->canusemmu = 0; - if (!stricmp(argv[i], "nocache")) - st->flags |= FLAGS_NOCACHE; - if (!stricmp(argv[i], "pal")) - st->flags |= FLAGS_FORCEPAL; - if (!stricmp(argv[i], "ntsc")) - st->flags |= FLAGS_FORCENTSC; - } - - if (!(SysBase->AttnFlags & AFF_68030)) - st->canusemmu = 0; - - if (st->canusemmu) { - if (!init_mmu(st)) { - printf("ERROR: MMU page table allocation failed.\n"); - st->canusemmu = 0; - } - } - - if (!parse_pass_1(f, st)) { - fseek(f, 0, SEEK_SET); - if (!parse_pass_2(f, st)) { - take_over(st); - } else { - printf("Pass #2 failed.\n"); - } - } else { - printf("Pass #1 failed.\n"); - } - - free(st); - - fclose(f); - - free_allocations(st); - - return 0; -} diff --git a/utilities/stateload/makefile b/utilities/stateload/makefile deleted file mode 100644 index f6a65e73..00000000 --- a/utilities/stateload/makefile +++ /dev/null @@ -1,26 +0,0 @@ - -NOWDATE := "\"$(shell date "+%-d.%-m.%Y")\"" -NOWTIME := "\"$(shell date "+%T")\"" - -CC=/opt/amiga/bin/m68k-amigaos-gcc -AS=/opt/amiga/bin/m68k-amigaos-as - -CFLAGS = -mcrt=nix13 -Os -m68000 -fomit-frame-pointer -msmall-code -DREVDATE=$(NOWDATE) -DREVTIME=$(NOWTIME) -LINK_CFLAGS = -mcrt=nix13 -s - -OBJS = main.o asm.o inflate.o mmu.o - -all: $(OBJS) - $(CC) $(LINK_CFLAGS) -o ussload $^ - -main.o: main.c - $(CC) $(CFLAGS) -I. -c -o $@ main.c - -mmu.o: mmu.c - $(CC) $(CFLAGS) -I. -c -o $@ mmu.c - -asm.o: asm.S - $(AS) -m68040 -o $@ asm.S - -inflate.o: inflate.S - $(CC) $(CFLAGS) -I. -c -o $@ inflate.S diff --git a/utilities/stateload/mmu.c b/utilities/stateload/mmu.c deleted file mode 100644 index 0fa24745..00000000 --- a/utilities/stateload/mmu.c +++ /dev/null @@ -1,206 +0,0 @@ - -/* I made this originally for AROS m68k */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "header.h" - -#define MMU030 1 -#define MMU040 2 -#define MMU060 3 - -#define CM_WRITETHROUGH 0 -#define CM_COPYBACK 1 -#define CM_SERIALIZED 2 -#define CM_NONCACHEABLE 3 - -#define LEVELA_SIZE 7 -#define LEVELB_SIZE 7 -#define LEVELC_SIZE 6 -#define PAGE_SIZE 12 // = 1 << 12 = 4096 - -/* Macros that hopefully make MMU magic a bit easier to understand.. */ - -#define LEVELA_VAL(x) ((((ULONG)(x)) >> (32 - (LEVELA_SIZE ))) & ((1 << LEVELA_SIZE) - 1)) -#define LEVELB_VAL(x) ((((ULONG)(x)) >> (32 - (LEVELA_SIZE + LEVELB_SIZE ))) & ((1 << LEVELB_SIZE) - 1)) -#define LEVELC_VAL(x) ((((ULONG)(x)) >> (32 - (LEVELA_SIZE + LEVELB_SIZE + LEVELC_SIZE))) & ((1 << LEVELC_SIZE) - 1)) - -#define LEVELA(root, x) (root[LEVELA_VAL(x)]) -#define LEVELB(a, x) (((ULONG*)(((ULONG)a) & ~((1 << (LEVELB_SIZE + 2)) - 1)))[LEVELB_VAL(x)]) -#define LEVELC(b, x) (((ULONG*)(((ULONG)b) & ~((1 << (LEVELC_SIZE + 2)) - 1)))[LEVELC_VAL(x)]) - -#define INVALID_DESCRIPTOR 0xDEAD0000 -#define ISINVALID(x) ((((ULONG)x) & 3) == 0) - -static BOOL map_region2(struct uaestate *st, void *addr, void *physaddr, ULONG size, BOOL invalid, BOOL writeprotect, BOOL supervisor, UBYTE cachemode); - - -static void map_pagetable(struct uaestate *st, void *addr, ULONG size) -{ - /* 68040+ MMU tables should be serialized */ - map_region2(st, addr, NULL, size, FALSE, FALSE, FALSE, CM_SERIALIZED); -} - -/* Allocate MMU descriptor page, it needs to be (1 << bits) * sizeof(ULONG) aligned */ -static ULONG alloc_descriptor(struct uaestate *st, UBYTE bits, UBYTE level) -{ - ULONG *desc, dout; - ULONG size = sizeof(ULONG) * (1 << bits); - ULONG ps = 1 << PAGE_SIZE; - UWORD i; - - while (st->page_free >= size && (((ULONG)st->page_ptr) & (size - 1))) { - st->page_ptr += 0x100; - st->page_free -= 0x100; - } - while (st->page_free < size) { - /* allocate in aligned blocks of PAGE_SIZE */ - UBYTE *mem, *newmem, *pagemem; - - // by design fail if no FAST RAM available - mem = AllocMem(2 * ps, MEMF_FAST); - if (!mem) - return 0; - Forbid(); - FreeMem(mem, 2 * ps); - newmem = (UBYTE*)((((ULONG)mem) + ps - 1) & ~(ps - 1)); - pagemem = allocate_abs(ps, (ULONG)newmem, st); - Permit(); - if (!pagemem) - return 0; - st->page_ptr = pagemem; - st->page_free = ps; - if (level > 0 && st->mmutype >= MMU040) - map_pagetable(st, pagemem, ps); - } - desc = (ULONG*)st->page_ptr; - for (i = 0; i < (1 << bits); i++) - desc[i] = INVALID_DESCRIPTOR; - dout = (ULONG)desc; - if (st->mmutype == MMU030) - dout |= 2; /* Valid 4 byte descriptor */ - else - dout |= 3; /* Resident descriptor */ - st->page_ptr += size; - st->page_free -= size; - return dout; -} - -static BOOL map_region2(struct uaestate *st, void *addr, void *physaddr, ULONG size, BOOL invalid, BOOL writeprotect, BOOL supervisor, UBYTE cachemode) -{ - ULONG desca, descb, descc, pagedescriptor; - ULONG page_size = 1 << PAGE_SIZE; - ULONG page_mask = page_size - 1; - - if ((size & page_mask) || (((ULONG)addr) & page_mask) || (((ULONG)physaddr) & page_mask)) - return FALSE; - if (physaddr == NULL) - physaddr = addr; - - while (size) { - desca = LEVELA(st->MMU_Level_A, addr); - if (ISINVALID(desca)) - desca = LEVELA(st->MMU_Level_A, addr) = alloc_descriptor(st, LEVELB_SIZE, 1); - if (ISINVALID(desca)) - return FALSE; - descb = LEVELB(desca, addr); - if (ISINVALID(descb)) - descb = LEVELB(desca, addr) = alloc_descriptor(st, LEVELC_SIZE, 2); - if (ISINVALID(descb)) - return FALSE; - descc = LEVELC(descb, addr); - - if (invalid) { - pagedescriptor = INVALID_DESCRIPTOR; - } else { - pagedescriptor = ((ULONG)physaddr) & ~page_mask; - BOOL wasinvalid = ISINVALID(descc); - if (st->mmutype == MMU030) { - pagedescriptor |= 1; // page descriptor - if (writeprotect || (!wasinvalid && (descc & 4))) - pagedescriptor |= 4; // write-protected - /* 68030 can only enable or disable caching */ - if (cachemode >= CM_SERIALIZED || (!wasinvalid && (descc & (1 << 6)))) - pagedescriptor |= 1 << 6; - } else { - pagedescriptor |= 3; // resident page - if (writeprotect || (!wasinvalid && (descc & 4))) - pagedescriptor |= 4; // write-protected - if (supervisor || (!wasinvalid && (descc & (1 << 7)))) - pagedescriptor |= 1 << 7; - // do not override non-cached - if (wasinvalid || cachemode > ((descc >> 5) & 3)) - pagedescriptor |= cachemode << 5; - else - pagedescriptor |= ((descc >> 5) & 3) << 5; - if (addr != 0 || size != page_size) - pagedescriptor |= 1 << 10; // global if not zero page - } - } - - LEVELC(descb, addr) = pagedescriptor; - size -= page_size; - addr += page_size; - physaddr += page_size; - } - return TRUE; -} - -BOOL map_region(struct uaestate *st, void *addr, void *physaddr, ULONG size, BOOL invalid, BOOL writeprotect, BOOL supervisor, UBYTE cachemode) -{ - if (addr != physaddr) - printf("MMU: Remap %08lx-%08lx -> %08lx (I=%d,WP=%d,S=%d)\n", addr, addr + size - 1, physaddr, invalid, writeprotect, supervisor); - if (!map_region2(st, addr, physaddr, size, invalid, writeprotect, supervisor, cachemode)) { - printf("MMU: Remap error\n"); - return FALSE; - } - return TRUE; -} - -BOOL unmap_region(struct uaestate *st, void *addr, ULONG size) -{ - printf("MMU: Unmapped %08lx-%08lx\n", addr, addr + size - 1); - return map_region2(st, addr, NULL, size, TRUE, FALSE, FALSE, 0); -} - -BOOL init_mmu(struct uaestate *st) -{ - st->MMU_Level_A = (ULONG*)(alloc_descriptor(st, LEVELA_SIZE, 0) & ~3); - if (!st->MMU_Level_A) - return FALSE; - st->mmutype = MMU030; - if (SysBase->AttnFlags & AFF_68040) - st->mmutype = MMU040; - if (st->mmutype >= MMU040) - map_pagetable(st, st->MMU_Level_A, 1 << PAGE_SIZE); - - // Create default 1:1 mapping - - // memory - Forbid(); - struct MemHeader *mh = (struct MemHeader*)SysBase->MemList.lh_Head; - while (mh->mh_Node.ln_Succ) { - ULONG mstart = ((ULONG)mh->mh_Lower) & 0xffff0000; - ULONG msize = ((((ULONG)mh->mh_Upper) + 0xffff) & 0xffff0000) - mstart; - map_region(st, (void*)mstart, (void*)mstart, msize, FALSE, FALSE, FALSE, CM_WRITETHROUGH); - mh = (struct MemHeader*)mh->mh_Node.ln_Succ; - } - Permit(); - // io - map_region(st, (void*)0xa00000, (void*)0xa00000, 0xc00000 - 0xa00000, FALSE, FALSE, FALSE, CM_NONCACHEABLE); - map_region(st, (void*)0xd80000, (void*)0xd80000, 0xe00000 - 0xd80000, FALSE, FALSE, FALSE, CM_NONCACHEABLE); - map_region(st, (void*)0xe80000, (void*)0xe80000, 0x080000, FALSE, FALSE, FALSE, CM_NONCACHEABLE); - // rom - map_region(st, (void*)0xe00000, (void*)0xe00000, 0x080000, FALSE, FALSE, FALSE, 0); - map_region(st, (void*)0xf80000, (void*)0xf80000, 0x080000, FALSE, FALSE, FALSE, 0); - - return TRUE; -} diff --git a/utilities/stateload/readme.txt b/utilities/stateload/readme.txt deleted file mode 100644 index 50ec56b8..00000000 --- a/utilities/stateload/readme.txt +++ /dev/null @@ -1,77 +0,0 @@ - -ussload is UAE state save file (*.uss) loader designed for real hardware. - -v1.1: - -- GVP MapROM support added. GVP A530 and most A2000 and A3000 GVP boards. -- Blizzard 1230 MKI/II/III/IV, 1240, 1260 MapROM support added. -- Switch off all floppy drive motors before memory decompression. -- Fixed crash if 68020 or 68030 statefile was loaded and CPU was - 68040 or 68060. -- Fixed uncompressed statefile support. -- Compatibility improved. - - -Supported state file hardware configurations: - -Common OCS/ECS 68000 A500 configurations. Chip RAM, "Slow" RAM and -Fast RAM supported. -Basic A1200 68020 configuration. "Slow" RAM and Fast RAM is also -supported. - -Information: - -- Compatible with KS 1.2 and newer. -- CPU should match state file config but 68020 to 68030 most likely works, - 68000 to 68020 or 68030 depends on program, 68020 to 68000 rarely works. -- RAM config must match (can be larger than required) and system must - have at least 512k more RAM than state file requires. -- Both compressed and uncompressed state files are supported. -- HD compatible (state file is completely loaded before system take over) -- KS ROM does not need to match if loaded program has already completely - taken over the system or supported Map ROM hardware is available. -- All state files should be supported, at least since UAE 0.8.22. -- State file restore can for example fail if state file was saved when - blitter was active or program was executing self-modifying code. - -Minimum RAM config examples: - -512k Chip RAM state file: hardware must have 1M Chip or 512k Chip+512k -"Slow" RAM or 512k Chip+512k real Fast. -512k+512k state file: hardware must have 1M+512k or 512k+1M or -512k+512k+512k real Fast. - -Note that uncompressed state files require at least 1M contiguous extra -RAM because all state file RAM address spaces need to fit in RAM before -system take over. -A1200 chip ram only state files usually require at least 1M Fast ram. - -Map ROM hardware support: - -Currently ACA500, ACA500plus, ACA1221, ACA1221EC and most ACA123x -variants Map ROM hardware is supported. -If state file ROM is not same as hardware ROM, ROM image is automatically -loaded from DEVS:Kickstarts and enabled if found. -Check WHDLoad documentation for DEVS:Kickstarts files and naming. -If A1200 KS 3.0 ROM is missing: manually copy correct ROM to -DEVS:Kickstarts and name it kick39106.a1200. - -Command line parameters: - -- nowait = don't wait for return key. -- debug = show debug information. -- test = parse and load state file, exit before system take over. -- nomaprom = do not use Map ROM. -- nocache = disable caches before starting loaded program (68020+ only) -- pal = force PAL mode (ECS/AGA only) -- ntsc = force NTSC mode (ECS/AGA only) - -Background colors: - -- purple = Map ROM copy. -- red = decompressing/copying Chip Ram state. -- green = decompressing/copying "Slow" RAM (0x00c00000) state. -- blue = decompressing/copying Fast RAM (0x00200000) state. -- yellow = configuring floppy drives (seek rw head, motor state). - -Source: https://github.com/tonioni/WinUAE/tree/master/utilities/stateload