Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal

GreaseMonkey

Members
  • Content Count

    36
  • Joined

  • Last visited

  • Days Won

    5

Posts posted by GreaseMonkey

  1. #  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x2abb37ec, pid=1852, tid=2888
    #
    # JRE version: Javaâ„¢ SE Runtime Environment (7.0_67-b01) (build 1.7.0_67-b01)
    # Java VM: Java HotSpotâ„¢ Client VM (24.65-b04 mixed mode windows-x86 )
    # Problematic frame:
    # C  [atioglxx.dll+0x437ec]
    
    Update your graphics drivers.

    While we're at it:

    # An error report file with more information is saved as:
    # C:\Users\Space Man\AppData\Roaming\.minecraft\hs_err_pid1852.log
    
    Paste that file here.
  2. This is something that I'm scratching my head over. It would be great if this were written in C (and if I had a dollar for every time I thought that... I think I'm up to about $5 now?), but alas, it isn't, and thus multiple return values are very much out of the question.

    Having a think about it, it would make sense if the bus ran at 1MHz. The Z80 currently runs at 2MHz, and all memory accesses on the Z80 tend to take a minimum of 3 cycles (in reality it's more like 2 cycles followed by a DRAM refresh but we'll just skip on that and assume the whole window is available for it). The MIPS3 core I'm working on also runs at 2MHz. I would like to be able to clock that at a higher speed than the main bus, but in order for that to work, the bus needs an API for it.

    Easy case: Only one CPU on the bus

     

    public int getTime(int cpuid);
    public int ensureTime(int cpuid, int currentTick);
    public int eatCycles(int cpuid, int startTick, int lengthInTicks);
    
    Reason for providing cpuid anyway is so that the same API can be used for a multi-CPU setup.

    Reason for returning an int in ensureTime is to get the correct point in time.

    How to access the bus (a proposal):

    int targetBusTime = this.currentTimeSliceBusTicks - (this.cycleBudget/this.clockMultiplier);
    int actualBusTime = memory.ensureTime(this.cpuid, targetBusTime);
    
    // do reads and writes here - eatCycles is called by the bus components
    
    int endBusTime = memory.getTime(this.cpuid);
    this.cycleBudget = this.currentTimeSliceCpuTicks - endBusTime;
    
    Of course, a more advanced CPU implementation would track this as a separate variable, and dispatch reads and writes in a manner that avoids stalling the CPU where possible.

    In a system which ignores the cpuid, these can be implemented like so:

     

    private int busTime = 0;
    
    private int onTickStart_ResetBusTime() {
        this.busTime = 0;
    }
    
    public int getTime(int cpuid) {
        return this.busTime;
    }
    
    public int ensureTime(int cpuid, int currentTick) {
        if(this.busTime < currentTick) {
            this.busTime = currentTick;
        }
        return this.busTime;
    }
    
    public int eatCycles(int cpuid, int startTick, int lengthInTicks) {
        ensureTime(startTick);
        this.busTime += lengthInTicks;
        return this.busTime;
    }
    
    Hard case: More than one CPU on the bus

    Oh yeah, the thing that makes this more fun? By "CPU", anything which does DMA could be classified as a "CPU".

    If all CPUs execute in parallel, then the one-CPU approach can work just fine. Otherwise, that bus is going to suffer horribly.

    Ultimately you need to track each CPU's busTime in an array (i.e. private int[] busArray;), and implement what is basically a memory allocator minus the memory.

    You'll basically need to track various windows into the bus in a sorted manner. I'd say a bitfield implemented in terms of ints would be the most suitable approach.

    As for ensuring that no one CPU can hog the bus the whole time, well, you could possibly inject a few windows into the bus on the bus controller. Or you could just punch anyone who decides to use a 6502 on a multiprocessor system.

    One more thing, I've just noticed an issue with this "time travel" approach: There is no guarantee that I/O will be executed in the correct order or RAM updated in the correct order between CPUs.

    Easy solution for hard case: Timeslicing

    Each CPU gets given a reasonably short timeslice of the bus. Possibly two timeslices per tick.

    Really easy solution for hard case: Don't even bother with accuracy

    Just run each CPU in its own thread and completely ignore this proposal. Simple.

  3. Just went back to reading this and I forgot that I ever read it.

    > The text parsing required is also fairly simple, even on an 8-bit architecture like the 6502.

    ...converting decimal strings to integers is pretty difficult on a 6502, actually.

    I get the feeling it would be better to have a text string for architectures which handle text strings well, which then ends in a \n (10, 0x0A) and a \x00 (0, 0x00). Following that should be a binary format.

    Or heck, this would be better:

     

    BOOT:Lua 5.2,Lua 5.3:512+1199\n
    BOOT:MikeKaraoke:64+102\n
    \x00(pad up to next 16-byte boundary w/ \x00 bytes, then binary data follows:)
    
    uint8_t magic; // 'B' for big-endian, 'b' for little-endian, 0x00 to terminate the boot list
    uint8_t block_length; // measured in 16-byte units
    uint16_t length; // measured in bytes
    uint32_t offset; // measured in bytes where the first byte of the disk is 0
    uint8_t archname[]; // NUL-terminated string
    
    {'b', 1, 2472, 3072, "OC-ARM"},
    {0x00, ...}
    
    After all that: \x00
    
    Alternatively, have binary boot records on sector 1, and text boot records on sector 0, which would be even better.

    > Generic names like "ARM" or "MIPS" should be avoided in favor of specific names like "OC-ARM" and "OCMIPS" and "OpenArms".

    Oh, I definitely did worse than that. OCMIPS uses boot.elf. By the way, that's a project that could do with someone keeping it up to date, possibly even getting the FPU to work more accurately. Perhaps mocha could work again?

  4. I've used that colour test pattern before, it's an oldie but a goodie.

    If you want to have some seriously good fun with it, try writing a raymarcher. I did that prior to BTM16 (not 16.2, just 16) and had something really good but it appears it got lost after the great chunk corruption incident.

  5. Going to quickly mention that there's two versions of DFPWM now (original DFPWM and DFPWM1a). If it sounds too slow, you have an old version of the mod (in that case it's using original DFPWM) and the tape is using DFPWM1a. If it sounds too fast, the mod is using DFPWM1a and the tape is using original DFPWM.

    Main reason 1a exists is because after a bit of component tweaking I managed to get it to sound *much* better than it used to. (It tends to beat MP3 at 48kbps now.)

    But yeah, what Lizzy said.

  6. The problem: event.pull returns multiple arguments, not a table with the names put into it. So "touch" will actually contain touch[2], touch[3] instead of touch.x, touch.y.

    Step 1: Tidy up your places table:

     

        local places = {}
        places.station = {x = 218, y = 151, z = 60}
        places.library = {x = 205, y = 112, z = 59}
        places.roomComputer = {x = 206, y = 106, z = 71}
        places.docks = {x = 218, y = 104, z = 77}
        places.roomWarLeft = {x = 221, y = 99, z = 70}
        places.roomWarRight = {x = 221, y = 99, z = 79}
        places.emergency = {x = 227, y = 99, z = 79}
        places.projector = {x = 207, y = 99, z = 76}
        places.roomBed = {x = 212, y = 91, z = 72}
    

    Step 2: Fix the loop. Here's one way to do it which mostly maintains the code style:

     

        while true do
          local touch = {}
          touch.screenAddress, touch.x, touch.y, touch.button, touch.playerName = event.pull("touch")
          for buttonName,buttonContent in pairs(buttons) do
            if ((touch.x >= buttonContent.x and touch.x < buttonContent.x + buttonContent.width) and (y >= buttonContent.y and y < buttonContent.y + buttonContent.height)) == true then --here is the error
              teleport(buttonName,touch.playerName)
            end
          end
        end
    
  7. Draft 1

     

    D1:   2016-08-05T02:45:39+00:00
    
    $ date -u -Iseconds
    
    ----

    There are two address spaces for all components: the config space, and the main I/O space.

    Every component has a VID (virtual ID) and that is how components are addressed. Every VID should be physically settable to any 8-bit value on each component. Any component with a VID set to 0xFF is rendered inaccessible by any methods that address by VID.

    Every component also has a PID (physical ID) which indicates the physical location of this component on a given bus master.

    The config space is read-only. Everything in the config space is readable by any bit width.

    CONFIG SPACE

    This bus is little-endian.

    These fields are compulsory, and every component needs to read at least the bottom 3 address bits:

    • 0x00[4]: 4-byte type ID. Forms a 4-char ASCII string.
    • 0x04[1]: Bus PID.
    • 0x05[1]: Bus master VID. 0xFF if using the root bus master.
    • 0x06[1]: Bus PID with all bits inverted.
    • 0x07[1]: Bus master VID with all bits inverted.
    These two fields are optional, and there is no requirement for bit 3 to be read:
    • 0x08[4]: 4-byte extension ID #1.
    • 0x0C[4]: 4-byte extension ID #2.
    Components are allowed to go further than this.

    Open bus is 0xFFFFFFFF, because that's what us low-level weirdos tend to expect. This applies to all busses. Because of this, if you have a type ID of 0xFFFFFFFF, that VID has no component using it.

    The root bus master (it'll be on your motherboard) is of course an exception to a lot of these rules:

    • VID is always 0xFF and it is completely unconfigurable.
    • PID is 0xFF too. So is the bus master VID.
    • If the ID is 0xFFFFFFFF, then this bus master cannot be reconfigured, but there's DEFINITELY a bus master here.
    • Basically, if you have a "dumb" bus master, the config space will be open bus, which also means that a bus conflict check will fail.
    Components should avoid using any I/O ports outside of 0x00-0x7F in its main I/O bus for ease of addressability with a lot of CPUs.

    Some components will have standard VID slots. Conflicts should be avoided where possible. Proposed standard slots:

    • 0x00: Various BIOS EEPROMs would probably end up using this.
    • 0xC0: MIPS BIOS EEPROM.
    • 0xDB: Serial debug interface. ID is "Dbg0". Write to 0x00 to output byte, read from 0x00 to input byte, -1 will be returned if no byte is available, bus is actually 32 bits wide, but can be accessed by byte, reads from 0x01-0x03 are buffered.
    For an example, here's how things would be addressed on MIPS:
    • 0x0+++++++: User virtual memory space
    • 0x800xxxxx: Cached RAM (bit mask is for 1MB)
    • 0xA00xxxxx: Uncached RAM (bit mask is for 1MB)
    • 0xBEvv00rr: Uncached Config space for VID=v, address=r
    • 0xBFvvrrrr: Uncached Main I/O space for VID=v, address=r
    • 0xC+++++++: Kernel virtual memory space
    CODE SAMPLES:

    These are in MIPS assembly. There is no op reordering, but I have decided to insert NOPs in delay slots just for the sake of readability. I have also decided to use the LA ("Load Address") pseudo-op as a load-immediate so things are a bit more obvious.

    To clarify: LA loads the 32-bit value you see there DIRECTLY - it does not do a memory load. (It's also reasonably likely to use 2 real ops, although I think there's really only one place here where it actually does.)

    I have tried to avoid MIPSisms here.

    Component presence detection: (ID in $a0, $v0 returns nonzero if there is a component)

    LA      $t0,      0xBE000000
    ANDI    $t1, $a0, 0x00FF
    SLL     $t1, $t1, 16
    ORI     $t0, $t0, $t1
    LW      $t1,      0x00($t0)
    NOP
    ADDIU   $v0, $v0, 1 // convert 0xFFFFFFFF -> 0
    JR      $ra
    NOP
    
    Bus conflict detection: (ID in $a0, $v0 returns nonzero if there is a conflict, note this will trigger if there is no component)

    LA      $t0,      0xBE000000
    ANDI    $t1, $a0, 0x00FF
    SLL     $t1, $t1, 16
    ORI     $t0, $t0, $t1
    LH      $t1,      0x04($t0) // LH is a signed load, thus you get a sign extension
    LH      $t2,      0x06($t0)
    NOP
    XOR     $v0, $t1, $t2
    ADDIU   $v0, $v0, 1 // convert 0xFFFFFFFF -> 0, or 0 -> 1
    JR      $ra
    NOP
    
    Fun thing, if there is no component here, you will get 1 in $v0, so you can do this:

    MOVE    $a0,      $s0
    J       detect_bus_conflict
    NOP
    LA      $t0,      1
    BEQ     $v0, $t0, _vid_does_not_exist
    NOP
    BNEZ    $v0,      _vid_has_bus_conflict
    NOP
    
    Finally, how to spew "Hello World!" down every Dbg0 device (as opposed to just assuming that it's at 0xDB):

    LA      $t0,      0xBE000000
    LA      $t1,      0x00010000
    LA      $t2,      255
    LA      $t3,      'Dbg0'
    
    _loop_find:
    
    // Detect Dbg0 component
    LW      $t4,      0x00($t0)
    NOP
    BNE     $t4, $t3, _loop_find_continue
    NOP
    
    //
    // Print hello message
    //
    LA      $t6,      str_hello
    LA      $t5,      0x01000000
    LB      $t7,      0($t6) // Preload first byte
    ADDU    $t5, $t5, $t0 // 0xBFxxxxxx address
    
    // Actual print loop
    _loop_hello:
    SB      $t7,      0($t5)
    ADDIU   $t6, $t6, 1
    LB      $t7,      0($t6)
    NOP
    BNEZ    $t7,      _loop_hello
    NOP
    
    // Advance loop
    _loop_find_continue:
    ADDIU   $t2, $t2, -1
    ADDU    $t0, $t0, $t1
    BNEZ    $t2,      _loop_find
    NOP
    
    // Return
    JR $ra
    NOP
    
    // Read-only data
    str_hello: .asciiz "Hello World!\n"
    
  8. Are you checking the files in-game or outside of it? You should be doing the former and not the latter.

    Do you have enough space on your disk to actually do this?

    You may have success if you do file:flush() before doing file:close(), but if that's what it takes to make it actually appear on disk, then that is probably a bug.

  9. First things first, I'll clean up what you have:

    --create fake testing data
    local testDensity = {}
    local j = 0
    for i=1,255 do
    	testDensity[i] = j
    	if j > 2 then
    		j = 0
    	else
    		j = j + 1
    	end
    end
    
    --opens test binary file
    local file = io.open("testBinaryFile", "wb")
    for i=1, 255 do
    	local d = testDensity[i]
    	file:write(string.char(d))
    end
    file:close()
    
    I'm not sure if io.close(file) is properly supported - it's a bit cleaner to just use file:close().

    Does that code work? I mean you still have one byte per value instead of 2 bits per value, but does it write data to the file now?

    In order to pack several values into a single byte, you'd probably want to shift left by 2*n or multiply by 4^n. Shifts are only available in Lua 5.3, but they're a cleaner option for this kind of thing. In order to read the data back you'll want to use a binary-AND (the & operator) and a right shift, and for that you need Lua 5.3, OR the 5.2 bit32 library (it's cleaner to use 5.3 to be blunt).

    So basically, you have to read and write 4 2bit values at a time.

  10. My understanding is that this forum is mostly for putting proposed standards and whatnot but it should be fine for fleshing out ideas for standards.

    The problem with this approach of course is you're basically sending a password in the clear. But having a standard protocol + port would be nice.

    I'd personally do away with the username+password scheme and instead just check if the sender is on a list of authorised IDs.

    Having session logic should not be necessary as if something needs to be returned over the modem, it should be embedded into the code to run.

    At this point you'd probably want to flesh out a standard API. Probably this:

    * remexec.auth_add(component_id)

    * remexec.auth_del(component_id)

    The calls themselves should be self-explanatory.

    Namespaces that should be included already:

    * component

    * computer

    * remexec

    Would something like that work?

  11. First things first, I assume you're selling it for in-game currency and not real money?

    With that said, you could do some form of Software as a Service thing in-game - all the robots are actually dumb slaves and the logic is handled by a master server.

    But the easiest solution is to use the robot's component address as an encraption key.

  12. Problem is, Unifont is licensed under the GPL (which means OC as a whole ends up under the GPL), while Unscii is public domain and is notably better for graphical stuff. Furthermore, the font used is actually a mix of Unscii and some PD Japanese + CJK font.

    What glyphs are missing? If they're linguistic ones you may want to draw them yourself.

  13. If the objective were to make a text editor... well, those things are very hard to write. Fortunately that's not what's being reguested.

    Under the title on the left side of the screen:

    ...what?

    The possibility to put a title in the middle of the screen:

    Unless you're making this the same size as all other text that will be tricky (it will involve writing your own font + font renderer).

    Otherwise: gpu.set(math.floor((screen_width-#title)/2)+1, title_y, title)

    Changing the colors of the text easily:

    If you use a Tier 2 GPU + screen you can use gpu.setPaletteColor(pal_idx, 0xFFFF00) and gpu.setForeground(pal_idx, true) for example.

    Not terminatible so nobody can shut it off:

    I'm pretty sure this question has been answered all over the place.

    Skipping OpenOS entirely and running on the "bare metal" is one way of doing this, although accessing components is a little tricky and you have to bind your screen to your GPU first.

    Possiblity to make a list with rules and people:

    (making a different list for the staff the members and member+):

    Should be pretty easy. Make sure you know what arrays are, or learn what they are, and make sure you use them.

    ----

    Honestly, the easiest solution is to just use the OC text editor on a user-locked computer. It won't do everything you want, but it is a nice and simple solution.

  14. If getting completely and utterly owned is what you are trying to achieve then this is a great idea.

    As for the rest of us, this is a horrible idea.

    You do not need a well-established SQL database software library. Loading and saving Lua tables should be fine. If you want something more robust. you'll have to use your imagination (it will probably involve using binary files).

  15. Here's some definitions from the OCMIPS ELF bootloader which you can use for whatever the hell you like:

    static const uint8_t e_ident_match[16+8] = 
    	"\x7F" "ELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    	"\x02\x00"
    	"\x08\x00" // Change this to match your architecture
    	"\x01\x00\x00\x00";
    
    struct ElfHeader
    {
    	uint8_t e_ident[16];
    	uint16_t e_type, e_machine;
    	uint32_t e_version;
    	uint32_t e_entry, e_phoff, e_shoff, e_flags;
    	uint16_t e_ehsize;
    	uint16_t e_phentsize, e_phnum;
    	uint16_t e_shentsize, e_shnum;
    	uint16_t e_shstrndx;
    };
    
    struct ProgHeader
    {
    	uint32_t p_type;
    	uint32_t p_offset;
    	uint32_t p_vaddr;
    	uint32_t p_paddr;
    	uint32_t p_filesz;
    	uint32_t p_memsz;
    	uint32_t p_flags;
    	uint32_t p_align;
    };
    
    #define PT_LOAD 0x00000001
    
    It's only for 32-bit ELF files - 64-bit ELF files have differently-sized fields.

    For e_ident_match you'll want to change it to match the first 24 bytes of the ELF you're trying to load, assuming you compiled it correctly.

    Here's how I build mocha (note the text-segment bit - this is where your ELF will be loaded):

     

    mipsel-none-elf-gcc -nostdlib -fno-builtin-headers -fno-builtin -Os -G0 -msoft-float -Wl,-Ttext-segment=0xA0005000 -o init.elf ${CSRCS} -lc -lgcc && \
    cp init.elf "${OUTDIR}/" && \
    mipsel-none-elf-strip "${OUTDIR}/init.elf" && \
    mipsel-none-elf-objdump -p init.elf && \
    ls -l init.elf "${OUTDIR}/init.elf" && \
    true
    
    Do not use dynamic linking. Just statically link it at the address you want it. If you want dynamic linking, do that in your main kernel, not in your bootloader. (It's hard. You normally go through the PT_DYNAMIC section and read your processor-specific ELF supplement to help you with the relocation types.)

    The general loading process goes like this:

    1. Load the header. (Verify the things you want in there.)

    2. Use e_phoff to find the program header list, and e_phnum to find out how many program headers there are in the list.

    3. Seek to e_phoff, and read e_phnum program header entries.

    4. For every program header with a p_type of 1 (PT_LOAD), allocate + zerofill p_memsz bytes at p_vaddr, and if p_filesz is nonzero, read p_filesz bytes from p_offset in the file into p_vaddr in memory.

    5. Jump to e_entry... That is:

     

    ((void (*)(void))(ehdr.e_entry))();
    
    That should be enough to boot a simple ELF from a bootloader. If you want the actual ELF docs, Google is your friend.

    Actually building the bootloader typically involves writing a GNU linker script and is outside of the scope of this document.

  16. If you want it to be pipable, use io.write() instead of term.write().

    Otherwise, pretty solid first Lua program. How long have you been programming for?

    EDIT: Also, consider using sublevel as an optional argument to list_tree, e.g.

    local function list_tree(path, sublevel)
      sublevel = sublevel or 1
    
  17. By "proper" I meant "current"

    My Linux port attempt uses Linux 4.1.13 which is the same version I am using on this laptop to write this message. So it's very much current.

    Yes, MS-DOS is a functional operating system. Not really a good candidate to run on OC though, because it's not freely available

    Use FreeDOS. I have that on my 266MHz Celeron.

    Heck, if you want something else that's "current", consider something like RTEMS. Or are you going to use the "not a desktop OS" excuse for that?

  18. I second this notion. There's a lot of stuff that needs to be discussed and there are serveral people with great ideas.

    OCMIPS was developed with the knowledge that there were AFAIK at least two ARM implementations, and I used gamax92's OC-Example-Architecture repo as a base for it. Alt-architecture stuff does get discussed in IRC. I even hear that someone's writing an x86 emulator.

    S3 linked a suggestion in IRC for a component bus heavily inspired by the ATM protocol. (I am not talking about automated ATM teller machines where you enter in your personal PIN number.) I suspect an approach like that may be more suitable than my hardbus proposal.

    The idea of having a multiarch-friendly way of booting a system came to mind today, which was loosely discussed on IRC.

    Filesystem-related ideas were also discussed. S3 has a partition table scheme lying around on one of his hard drives, and apparently FAT12/FAT16 isn't too hard to do.

    Also:

    [00:32:33] <S3> The subforum could be called "Architectures and specifications"

    [00:32:51] <S3> maybe without the s

    [00:32:54] <S3> sounds better imo

    [00:32:59] <S3> "Architecture and Specifications"

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.