Hex viewer is now a hex editor!
This commit is contained in:
parent
094e278212
commit
89c0f95219
2
disk.c
2
disk.c
@ -100,7 +100,7 @@ uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_
|
|||||||
|
|
||||||
// TODO Do error handling
|
// TODO Do error handling
|
||||||
if (!useCHS) {
|
if (!useCHS) {
|
||||||
// LBA Read
|
// LBA Write
|
||||||
v86disk_addr_packet.start_block = sector;
|
v86disk_addr_packet.start_block = sector;
|
||||||
v86disk_addr_packet.blocks = count;
|
v86disk_addr_packet.blocks = count;
|
||||||
v86disk_addr_packet.transfer_buffer =
|
v86disk_addr_packet.transfer_buffer =
|
||||||
|
3
kernel.c
3
kernel.c
@ -309,6 +309,7 @@ void FileSelect() {
|
|||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_P:
|
case KEY_P:
|
||||||
|
if (IsDir(&entries[fileHovered])) break;
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
||||||
create_child(0x380000, (uintptr_t)ProgramLoadTest, 2, current_path, &vi);
|
create_child(0x380000, (uintptr_t)ProgramLoadTest, 2, current_path, &vi);
|
||||||
SetVideo25Lines();
|
SetVideo25Lines();
|
||||||
@ -316,6 +317,7 @@ void FileSelect() {
|
|||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_X:
|
case KEY_X:
|
||||||
|
if (IsDir(&entries[fileHovered])) break;
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
||||||
//HexViewTest(path, &vi);
|
//HexViewTest(path, &vi);
|
||||||
create_child(0x380000, (uintptr_t)HexViewTest, 2, current_path, &vi);
|
create_child(0x380000, (uintptr_t)HexViewTest, 2, current_path, &vi);
|
||||||
@ -324,6 +326,7 @@ void FileSelect() {
|
|||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_T:
|
case KEY_T:
|
||||||
|
if (IsDir(&entries[fileHovered])) break;
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
|
||||||
//TextViewTest(path, &vi);
|
//TextViewTest(path, &vi);
|
||||||
create_child(0x380000, (uintptr_t)TextViewTest, 2, current_path, &vi);
|
create_child(0x380000, (uintptr_t)TextViewTest, 2, current_path, &vi);
|
||||||
|
416
progs.c
416
progs.c
@ -5,62 +5,275 @@
|
|||||||
void HexViewTest(uint8_t *path, VOLINFO *vi) {
|
void HexViewTest(uint8_t *path, VOLINFO *vi) {
|
||||||
uint32_t err;
|
uint32_t err;
|
||||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||||
|
uint32_t screenSize = 80*25;
|
||||||
uint8_t *scratch = (uint8_t *)0x20000;
|
uint8_t *scratch = (uint8_t *)0x20000;
|
||||||
|
|
||||||
|
const uint32_t blockSize = 0x10000; // 64K
|
||||||
|
const uint32_t blockMask = ~0xffff; // block = (offset & blockMask)
|
||||||
|
const uint32_t blockShift = 16; // blockSize = 1 << blockShift
|
||||||
|
const uint32_t maxFileSize = 0x80000000; // 2GB
|
||||||
|
const uint32_t totalBlocks = maxFileSize / blockSize;
|
||||||
|
// TODO This hackish code means we should really be loading these
|
||||||
|
// programs rather than having them all be in the kernel itself
|
||||||
|
uint16_t (*writtenMap)[totalBlocks] =
|
||||||
|
(uint16_t (*)[totalBlocks])0x400000;
|
||||||
|
uint32_t (*blockLenMap)[totalBlocks] =
|
||||||
|
(uint32_t (*)[totalBlocks])((uintptr_t)writtenMap + sizeof(*writtenMap));
|
||||||
|
uint8_t (*writeStore)[blockSize] =
|
||||||
|
(uint8_t (*)[blockSize])((uintptr_t)blockLenMap + sizeof(*blockLenMap));
|
||||||
|
for (int i = 0; i < totalBlocks; i++)
|
||||||
|
(*writtenMap)[i] = 0;
|
||||||
|
uint8_t *screenBuff = *writeStore;
|
||||||
|
// First two blocks are screen buffer
|
||||||
|
uint32_t nextFreeBlock = 2;
|
||||||
|
|
||||||
FILEINFO fi;
|
FILEINFO fi;
|
||||||
err = DFS_OpenFile(vi, path, DFS_READ, scratch, &fi);
|
vga_text = (uint16_t *)0xb8000;
|
||||||
|
for (int i = 0; i < 80*50; i++)
|
||||||
|
vga_text[i] = 0x0f00;
|
||||||
|
err = DFS_OpenFile(vi, path, DFS_READ | DFS_WRITE, scratch, &fi);
|
||||||
if (err) {
|
if (err) {
|
||||||
vga_text += printStr("Open Error: ", vga_text);
|
vga_text += printStr("Open Error: ", vga_text);
|
||||||
printDword(err, vga_text);
|
printDword(err, vga_text);
|
||||||
|
kbd_wait();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t successcount;
|
if (fi.filelen == 0) {
|
||||||
uint32_t readOffset = 0, lastReadOffset = -1;
|
vga_text += printStr("File ", vga_text);
|
||||||
|
vga_text += printStr((char*)path, vga_text);
|
||||||
|
vga_text += printStr(" has no data.", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fi.filelen > maxFileSize) {
|
||||||
|
vga_text += printStr("File ", vga_text);
|
||||||
|
vga_text += printStr((char*)path, vga_text);
|
||||||
|
vga_text += printStr(" is too large (> 2GB).", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t drawOffset = 0, lastDrawOffset = -1;
|
||||||
char cont = 1;
|
char cont = 1;
|
||||||
uint32_t byteCount = 16*24, lastByteCount;
|
uint32_t byteCount = 16*24, lastByteCount = 0;
|
||||||
uint32_t screenSize = 80*25;
|
// Cursor offset from *drawOff*
|
||||||
char reread;
|
int32_t cursorScreenOff = 0, lastCursorScreenOff = -1;
|
||||||
|
// Pointer to last cursor in *VGA mem*
|
||||||
|
uint8_t *lastCursorScreenPtr = (uint8_t*)0xb8000;
|
||||||
|
char cursorNibble = 1, lastCursorNibble = 0;
|
||||||
|
char cursorRedraw = 1;
|
||||||
|
char reread = 1, redraw = 1;
|
||||||
|
uint8_t *currBuff = 0, *nextBuff = 0;
|
||||||
|
uint32_t currBuffLength, nextBuffLength, totalBuffLength;
|
||||||
|
uint16_t currLoadedBlock = -1, nextLoadedBlock = -1;
|
||||||
|
char currInMap = 0, nextInMap = 0;
|
||||||
|
uint32_t changeOffset = -1, lastChangeOffset = -1;
|
||||||
|
char fileChanged = 0;
|
||||||
for (;cont;) {
|
for (;cont;) {
|
||||||
uint8_t diskReadBuf[byteCount];
|
// Check if we need to scroll screen for cursor
|
||||||
if (readOffset != lastReadOffset) {
|
// Should never be more than 16 away, if it is,
|
||||||
lastReadOffset = readOffset;
|
// things will be caught by sanity checks.
|
||||||
|
// Scroll Back
|
||||||
|
if (cursorScreenOff < 0) {
|
||||||
|
if (drawOffset - 16 < fi.filelen)
|
||||||
|
drawOffset -= 16;
|
||||||
|
cursorScreenOff += 16;
|
||||||
|
}
|
||||||
|
// Scroll Forward
|
||||||
|
if (cursorScreenOff >= byteCount) {
|
||||||
|
if (drawOffset + 16 < fi.filelen)
|
||||||
|
drawOffset += 16;
|
||||||
|
cursorScreenOff -= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity checks
|
||||||
|
if (cursorScreenOff >= byteCount)
|
||||||
|
cursorScreenOff = byteCount - 1;
|
||||||
|
if (cursorScreenOff + drawOffset >= fi.filelen)
|
||||||
|
cursorScreenOff = fi.filelen - drawOffset - 1;
|
||||||
|
if (cursorScreenOff < 0) cursorScreenOff = 0;
|
||||||
|
|
||||||
|
if (cursorNibble != lastCursorNibble)
|
||||||
|
cursorRedraw = 1;
|
||||||
|
if (cursorScreenOff != lastCursorScreenOff)
|
||||||
|
cursorRedraw = 1;
|
||||||
|
if (cursorRedraw) {
|
||||||
|
const uint32_t hexViewScreenOff = 10 * 2;
|
||||||
|
const uint32_t asciiViewScreenOff = 61 * 2;
|
||||||
|
uint16_t *screen = (uint16_t*)0xb8000;
|
||||||
|
// Byte draw starts on first line
|
||||||
|
uint16_t *line = &screen[80 * (1 + (cursorScreenOff >> 4))];
|
||||||
|
uint8_t *cursorPtr = (uint8_t*)line;
|
||||||
|
if (cursorNibble == 0) {
|
||||||
|
// Each byte takes 3 chars on screen
|
||||||
|
cursorPtr += hexViewScreenOff + (cursorScreenOff & 0xF) * 3 * 2;
|
||||||
|
if ((cursorScreenOff & 0xF) > 7)
|
||||||
|
cursorPtr += 2;
|
||||||
|
// Low nibble
|
||||||
|
cursorPtr += 2;
|
||||||
|
} else if (cursorNibble == 1) {
|
||||||
|
// Each byte takes 3 chars on screen
|
||||||
|
cursorPtr += hexViewScreenOff + (cursorScreenOff & 0xF) * 3 * 2;
|
||||||
|
if ((cursorScreenOff & 0xF) > 7)
|
||||||
|
cursorPtr += 2;
|
||||||
|
// ASCII area
|
||||||
|
} else {
|
||||||
|
// Each byte takes 1 char on screen
|
||||||
|
cursorPtr += asciiViewScreenOff + (cursorScreenOff & 0xF) * 2;
|
||||||
|
}
|
||||||
|
// We want the color byte, not char
|
||||||
|
cursorPtr++;
|
||||||
|
if (cursorPtr != lastCursorScreenPtr) {
|
||||||
|
*lastCursorScreenPtr = 0x0f;
|
||||||
|
*cursorPtr = 0xf0;
|
||||||
|
lastCursorScreenPtr = cursorPtr;
|
||||||
|
}
|
||||||
|
lastCursorScreenOff = cursorScreenOff;
|
||||||
|
lastCursorNibble = cursorNibble;
|
||||||
|
cursorRedraw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((drawOffset & blockMask) != (lastDrawOffset & blockMask)) {
|
||||||
|
lastDrawOffset = (drawOffset & blockMask);
|
||||||
reread = 1;
|
reread = 1;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
if (drawOffset != lastDrawOffset) {
|
||||||
|
lastDrawOffset = drawOffset;
|
||||||
|
redraw = 1;
|
||||||
}
|
}
|
||||||
if (byteCount != lastByteCount) {
|
if (byteCount != lastByteCount) {
|
||||||
lastByteCount = byteCount;
|
lastByteCount = byteCount;
|
||||||
reread = 1;
|
redraw = 1;
|
||||||
}
|
}
|
||||||
|
if (changeOffset != lastChangeOffset) {
|
||||||
|
redraw = 1;
|
||||||
|
lastChangeOffset = changeOffset;
|
||||||
|
}
|
||||||
|
// Check for changes to block
|
||||||
|
if (changeOffset != -1) {
|
||||||
|
char isCurr = changeOffset < blockSize;
|
||||||
|
char changeInMap = isCurr ? currInMap : nextInMap;
|
||||||
|
uint8_t *changedBlock = isCurr ? currBuff : nextBuff;
|
||||||
|
// If changes are in map we don't need to do anything
|
||||||
|
if (!changeInMap) {
|
||||||
|
uint16_t loadedBlock = isCurr ? currLoadedBlock : nextLoadedBlock;
|
||||||
|
uint16_t storeBlockIdx = (*writtenMap)[loadedBlock];
|
||||||
|
// Add a new map entry
|
||||||
|
if (!storeBlockIdx) {
|
||||||
|
(*writtenMap)[loadedBlock] = storeBlockIdx = nextFreeBlock++;
|
||||||
|
(*blockLenMap)[loadedBlock] = isCurr ? currBuffLength : nextBuffLength;
|
||||||
|
}
|
||||||
|
uint8_t *storeBlock = writeStore[storeBlockIdx];
|
||||||
|
for (int i = 0; i < blockSize; i++)
|
||||||
|
storeBlock[i] = changedBlock[i];
|
||||||
|
// Move the current buffer to map
|
||||||
|
if (isCurr) { currBuff = storeBlock; currInMap = 1; }
|
||||||
|
else { nextBuff = storeBlock; nextInMap = 1; }
|
||||||
|
}
|
||||||
|
changeOffset = -1;
|
||||||
|
fileChanged = 1;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (reread) {
|
if (reread) {
|
||||||
|
// TODO We should probably check if we already have
|
||||||
|
// the block to read in nextBuff from previous stuff
|
||||||
|
// We are in a modified block
|
||||||
|
uint16_t newBlock = drawOffset >> blockShift;
|
||||||
|
if ((*writtenMap)[newBlock]) {
|
||||||
|
currBuff = writeStore[(*writtenMap)[newBlock]];
|
||||||
|
currBuffLength = (*blockLenMap)[newBlock];
|
||||||
|
totalBuffLength = currBuffLength;
|
||||||
|
currInMap = 1;
|
||||||
|
// We are in an unmodified block
|
||||||
|
} else {
|
||||||
|
uint32_t blockOffset = drawOffset & blockMask;
|
||||||
|
vga_text = &((uint16_t*)0xb8000)[80];
|
||||||
|
DFS_Seek(&fi, blockOffset, scratch);
|
||||||
|
if (fi.pointer != blockOffset) {
|
||||||
|
vga_text += printStr("Seek Error", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
err = DFS_ReadFile(&fi, scratch, screenBuff, &currBuffLength, blockSize);
|
||||||
|
if (err && err != DFS_EOF) {
|
||||||
|
vga_text += printStr("Read Error: ", vga_text);
|
||||||
|
printDword(err, vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currBuff = screenBuff;
|
||||||
|
totalBuffLength = currBuffLength;
|
||||||
|
currInMap = 0;
|
||||||
|
}
|
||||||
|
currLoadedBlock = newBlock;
|
||||||
|
reread = 0;
|
||||||
|
nextInMap = 0;
|
||||||
|
}
|
||||||
|
// We will be drawing stuff in the next block
|
||||||
|
// TODO This would be better served with nice functions!
|
||||||
|
if (currBuffLength == blockSize && (drawOffset & ~blockMask) > (blockSize - byteCount)) {
|
||||||
|
// TODO We should probably check if we already have
|
||||||
|
// the next block in currBuff from previous stuff
|
||||||
|
// Next is a modified block
|
||||||
|
uint16_t newBlock = (drawOffset >> blockShift) + 1;
|
||||||
|
if (nextLoadedBlock != newBlock) {
|
||||||
|
if ((*writtenMap)[newBlock]) {
|
||||||
|
nextBuffLength = (*blockLenMap)[newBlock];
|
||||||
|
nextBuff = writeStore[(*writtenMap)[newBlock]];
|
||||||
|
nextInMap = 1;
|
||||||
|
// Next is an unmodified block
|
||||||
|
} else {
|
||||||
|
uint32_t blockOffset = (drawOffset & blockMask) + blockSize;
|
||||||
|
vga_text = &((uint16_t*)0xb8000)[80];
|
||||||
|
DFS_Seek(&fi, blockOffset, scratch);
|
||||||
|
if (fi.pointer != blockOffset) {
|
||||||
|
vga_text += printStr("Seek Error", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
err = DFS_ReadFile(&fi, scratch, &screenBuff[blockSize], &nextBuffLength, blockSize);
|
||||||
|
if (err && err != DFS_EOF) {
|
||||||
|
vga_text += printStr("Read Error: ", vga_text);
|
||||||
|
printDword(err, vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nextBuff = &screenBuff[blockSize];
|
||||||
|
nextInMap = 0;
|
||||||
|
}
|
||||||
|
nextLoadedBlock = newBlock;
|
||||||
|
}
|
||||||
|
totalBuffLength = currBuffLength + nextBuffLength;
|
||||||
|
}
|
||||||
|
if (redraw) {
|
||||||
vga_text = (uint16_t *)0xb8000;
|
vga_text = (uint16_t *)0xb8000;
|
||||||
for (int i = 0; i < screenSize; i++)
|
|
||||||
vga_text[i] = 0x0f00;
|
|
||||||
vga_text += printStr((char*)path, vga_text);
|
vga_text += printStr((char*)path, vga_text);
|
||||||
|
vga_text += printChar(fileChanged ? '*' : ' ', vga_text);
|
||||||
{
|
{
|
||||||
const char prnt[] = "Scroll: Up/Down PgUp/PgDown Home/End Exit: E ";
|
const char prnt[] = "Scroll: Up/Down PgUp/PgDown Home/End Exit: F1";
|
||||||
vga_text = &((uint16_t*)0xb8000)[80-sizeof(prnt)];
|
vga_text = &((uint16_t*)0xb8000)[80-sizeof(prnt)];
|
||||||
vga_text += printStr((char*)prnt, vga_text);
|
vga_text += printStr((char*)prnt, vga_text);
|
||||||
}
|
}
|
||||||
vga_text = &((uint16_t*)0xb8000)[80];
|
vga_text = &((uint16_t*)0xb8000)[80];
|
||||||
DFS_Seek(&fi, readOffset, scratch);
|
uint32_t offsetInBuff = drawOffset & ~blockMask;
|
||||||
if (fi.pointer != readOffset) {
|
uint8_t *drawFromBuff = &currBuff[offsetInBuff];
|
||||||
vga_text += printStr("Seek Error", vga_text);
|
uint32_t maxDrawLen = totalBuffLength - (drawOffset & ~blockMask);
|
||||||
return;
|
for (int i = 0; i < maxDrawLen && i < byteCount; i += 16) {
|
||||||
}
|
// Blocks are blockSize aligned, so 16-byte alignment should work
|
||||||
err = DFS_ReadFile(&fi, scratch, diskReadBuf, &successcount, byteCount);
|
if (i + offsetInBuff >= blockSize) {
|
||||||
if (err && err != DFS_EOF) {
|
drawFromBuff = &nextBuff[-i];
|
||||||
vga_text += printStr("Read Error: ", vga_text);
|
offsetInBuff = 0;
|
||||||
printDword(err, vga_text);
|
}
|
||||||
return;
|
vga_text += printDword(i + drawOffset, vga_text);
|
||||||
}
|
|
||||||
for (uint32_t i = 0; i < successcount && i < byteCount; i += 16) {
|
|
||||||
vga_text += printDword(i + readOffset, vga_text);
|
|
||||||
vga_text += printChar(' ', vga_text);
|
vga_text += printChar(' ', vga_text);
|
||||||
vga_text += printChar(' ', vga_text);
|
vga_text += printChar(' ', vga_text);
|
||||||
for (uint32_t j = 0; j < 16; j++) {
|
for (uint32_t j = 0; j < 16; j++) {
|
||||||
if (i + j < successcount)
|
if (i + j < maxDrawLen)
|
||||||
vga_text += printByte(diskReadBuf[i + j], vga_text);
|
vga_text += printByte(drawFromBuff[i + j], vga_text);
|
||||||
else {
|
else {
|
||||||
vga_text += printChar(' ', vga_text);
|
vga_text += printChar(' ', vga_text);
|
||||||
vga_text += printChar(' ', vga_text);
|
vga_text += printChar(' ', vga_text);
|
||||||
}
|
}
|
||||||
vga_text += printChar(' ', vga_text);
|
vga_text += printChar(' ', vga_text);
|
||||||
if (j == 7)
|
if (j == 7)
|
||||||
@ -69,49 +282,88 @@ void HexViewTest(uint8_t *path, VOLINFO *vi) {
|
|||||||
vga_text += printChar(' ', vga_text);
|
vga_text += printChar(' ', vga_text);
|
||||||
vga_text += printChar('|', vga_text);
|
vga_text += printChar('|', vga_text);
|
||||||
for (uint32_t j = 0; j < 16; j++) {
|
for (uint32_t j = 0; j < 16; j++) {
|
||||||
if (i + j < successcount)
|
if (i + j < maxDrawLen)
|
||||||
vga_text += printChar(diskReadBuf[i + j], vga_text);
|
vga_text += printChar(drawFromBuff[i + j], vga_text);
|
||||||
else vga_text += printChar(' ', vga_text);
|
else vga_text += printChar(' ', vga_text);
|
||||||
}
|
}
|
||||||
vga_text += printChar('|', vga_text);
|
vga_text += printChar('|', vga_text);
|
||||||
vga_text = nextLine(vga_text);
|
vga_text = nextLine(vga_text);
|
||||||
}
|
}
|
||||||
reread = 0;
|
// Clear remainder of screen
|
||||||
|
for (;vga_text < &((uint16_t*)0xb8000)[screenSize]; vga_text++)
|
||||||
|
*vga_text = 0x0f00;
|
||||||
|
redraw = 0;
|
||||||
}
|
}
|
||||||
uint16_t key = get_scancode();
|
uint16_t key = get_scancode();
|
||||||
union V86Regs_t regs;
|
union V86Regs_t regs;
|
||||||
FARPTR v86_entry;
|
FARPTR v86_entry;
|
||||||
|
char try_edit = 0;
|
||||||
switch (key & 0xff) {
|
switch (key & 0xff) {
|
||||||
case KEY_DOWN: // down
|
case KEY_DOWN:
|
||||||
if ((readOffset + byteCount) < fi.filelen)
|
// Stay in file
|
||||||
readOffset += byteCount;
|
if ((cursorScreenOff + 16 + drawOffset) < fi.filelen)
|
||||||
else goto end;
|
cursorScreenOff += 16;
|
||||||
break;
|
break;
|
||||||
case KEY_UP: // up
|
case KEY_UP:
|
||||||
if ((readOffset - byteCount) < fi.filelen)
|
// Stay in file
|
||||||
readOffset -= byteCount;
|
if ((uint32_t)(cursorScreenOff - 16 + drawOffset) < fi.filelen)
|
||||||
else goto home;
|
cursorScreenOff -= 16;
|
||||||
|
break;
|
||||||
|
case KEY_LEFT:
|
||||||
|
if (cursorNibble == 0) { cursorNibble = 1; break; }
|
||||||
|
// Exiting text area
|
||||||
|
else if (cursorNibble == 2 && (cursorScreenOff & 0xF) == 0) {
|
||||||
|
cursorNibble = 0;
|
||||||
|
cursorScreenOff |= 0xF;
|
||||||
|
// Stay in file
|
||||||
|
} else if ((cursorScreenOff - 1 + drawOffset) < fi.filelen) {
|
||||||
|
cursorScreenOff--;
|
||||||
|
if (cursorNibble == 1) cursorNibble = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_RIGHT:
|
||||||
|
if (cursorNibble == 1) { cursorNibble = 0; break; }
|
||||||
|
// Entering text area
|
||||||
|
else if (cursorNibble == 0 && (cursorScreenOff & 0xF) == 0xF) {
|
||||||
|
cursorNibble = 2;
|
||||||
|
cursorScreenOff &= ~0xF;
|
||||||
|
// Stay in file
|
||||||
|
} else if ((cursorScreenOff + 1 + drawOffset) < fi.filelen) {
|
||||||
|
cursorScreenOff++;
|
||||||
|
if (cursorNibble == 0) cursorNibble = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_PGDOWN:
|
case KEY_PGDOWN:
|
||||||
if ((readOffset + (byteCount*4)) < fi.filelen)
|
if (drawOffset + byteCount < fi.filelen)
|
||||||
readOffset += (byteCount*4);
|
drawOffset += byteCount;
|
||||||
else goto end;
|
else if ((fi.filelen / byteCount) * byteCount > drawOffset)
|
||||||
|
drawOffset = (fi.filelen / byteCount) * byteCount;
|
||||||
break;
|
break;
|
||||||
case KEY_PGUP:
|
case KEY_PGUP:
|
||||||
if ((readOffset - (byteCount*4)) < fi.filelen)
|
if (drawOffset - byteCount < fi.filelen)
|
||||||
readOffset -= (byteCount*4);
|
drawOffset -= byteCount;
|
||||||
else goto home;
|
else drawOffset = 0;
|
||||||
break;
|
break;
|
||||||
case KEY_HOME: home:
|
case KEY_HOME:
|
||||||
readOffset = 0;
|
cursorScreenOff &= ~0xF;
|
||||||
|
if (cursorNibble == 0) cursorNibble = 1;
|
||||||
break;
|
break;
|
||||||
case KEY_END: end:
|
case KEY_END:
|
||||||
if ((fi.filelen / byteCount) * byteCount > readOffset)
|
cursorScreenOff |= 0xF;
|
||||||
readOffset = (fi.filelen / byteCount) * byteCount;
|
if (cursorNibble == 1) cursorNibble = 0;
|
||||||
break;
|
break;
|
||||||
case KEY_E: // e
|
case KEY_F1:
|
||||||
cont = 0;
|
cont = 0;
|
||||||
break;
|
break;
|
||||||
|
case KEY_F3: // start of file
|
||||||
|
drawOffset = 0;
|
||||||
|
break;
|
||||||
|
case KEY_F4: // end of file
|
||||||
|
if ((fi.filelen / byteCount) * byteCount > drawOffset)
|
||||||
|
drawOffset = (fi.filelen / byteCount) * byteCount;
|
||||||
|
break;
|
||||||
|
case KEY_F6: // TODO write file
|
||||||
|
break;
|
||||||
case KEY_F2:
|
case KEY_F2:
|
||||||
if (byteCount != 16*24) {
|
if (byteCount != 16*24) {
|
||||||
SetVideo25Lines();
|
SetVideo25Lines();
|
||||||
@ -129,8 +381,68 @@ void HexViewTest(uint8_t *path, VOLINFO *vi) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
try_edit = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!try_edit) continue;
|
||||||
|
// Check if in range
|
||||||
|
char k = key >> 8; // ASCII portion
|
||||||
|
char v;
|
||||||
|
if (cursorNibble == 2 && k >= 0x20 && k <= 0x7E) v = k;
|
||||||
|
else if (k >= '0' && k <= '9')
|
||||||
|
v = k - '0';
|
||||||
|
else if (k >= 'a' && k <= 'f')
|
||||||
|
v = k - 'a' + 0xA;
|
||||||
|
else if (k >= 'A' && k <= 'F')
|
||||||
|
v = k - 'A' + 0xA;
|
||||||
|
else continue;
|
||||||
|
// Change buffer at cursor
|
||||||
|
uint32_t screenOffsetInBuff = drawOffset & ~blockMask;
|
||||||
|
changeOffset = screenOffsetInBuff + cursorScreenOff;
|
||||||
|
char isCurr = changeOffset < blockSize;
|
||||||
|
uint8_t *changeBuff = isCurr ? currBuff : nextBuff;
|
||||||
|
uint32_t changeOffsetInBuff = isCurr ? changeOffset : changeOffset - blockSize;
|
||||||
|
if (cursorNibble == 0)
|
||||||
|
changeBuff[changeOffsetInBuff] = (changeBuff[changeOffsetInBuff] & 0xF0) | v;
|
||||||
|
else if (cursorNibble == 1)
|
||||||
|
changeBuff[changeOffsetInBuff] = (changeBuff[changeOffsetInBuff] & 0x0F) | (v << 4);
|
||||||
|
else changeBuff[changeOffsetInBuff] = v;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
if (!fileChanged) return;
|
||||||
|
vga_text = (uint16_t*)0xb8000;
|
||||||
|
vga_text += printStr((char*)path, vga_text);
|
||||||
|
vga_text += printChar(fileChanged ? '*' : ' ', vga_text);
|
||||||
|
vga_text += printChar(' ', vga_text);
|
||||||
|
vga_text += printStr("Save changes to file? (Y/N)", vga_text);
|
||||||
|
for (;vga_text < &((uint16_t*)0xb8000)[80];vga_text++)
|
||||||
|
*vga_text = 0x0f00;
|
||||||
|
uint16_t key=0;
|
||||||
|
for(;(key & 0xff) != KEY_N && (key & 0xff) != KEY_Y;key = get_scancode());
|
||||||
|
if ((key & 0xff) != KEY_Y) return;
|
||||||
|
// Write changes
|
||||||
|
for (int i = 0; i < totalBlocks && (i << blockShift) < fi.filelen; i++) {
|
||||||
|
// No change in current block
|
||||||
|
uint16_t blockIdx = (*writtenMap)[i];
|
||||||
|
uint32_t blockLen = (*blockLenMap)[i];
|
||||||
|
if (!blockIdx) continue;
|
||||||
|
// Write block to file
|
||||||
|
uint32_t successcount;
|
||||||
|
uint32_t blockOff = i << blockShift;
|
||||||
|
DFS_Seek(&fi, blockOff, scratch);
|
||||||
|
if (fi.pointer != blockOff) {
|
||||||
|
vga_text = (uint16_t*)0xb8000;
|
||||||
|
vga_text += printStr("Seek Error ", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t err = DFS_WriteFile(&fi, scratch, writeStore[blockIdx], &successcount, blockLen);
|
||||||
|
if (successcount < blockLen || err) {
|
||||||
|
vga_text = (uint16_t*)0xb8000;
|
||||||
|
vga_text += printStr("Write Error ", vga_text);
|
||||||
|
kbd_wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TextViewTest(uint8_t *path, VOLINFO *vi) {
|
void TextViewTest(uint8_t *path, VOLINFO *vi) {
|
||||||
|
Loading…
Reference in New Issue
Block a user